自己写了一个收发文件的程序:
发文件程序:
void CFileTransferDlg::OnBnClickedButtonSendFile()
{ServerSocket = socket( PF_INET, SOCK_STREAM, 0 ); //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons( usHostPort );if ( bind( ServerSocket,(LPSOCKADDR)&m_sockServerAddr, sizeof(m_sockServerAddr) ) == SOCKET_ERROR ) //与选定的端口绑定
{
MessageBox(_T("无法绑定服务器!"),_T("Socket"), MB_OK|MB_ICONEXCLAMATION);
return;
}if ( listen(ServerSocket,1) == SOCKET_ERROR ) //开始监听客户连接请求
{
MessageBox(_T("服务器监听失败!"),_T("Socket"), MB_OK|MB_ICONEXCLAMATION);
return;
}CString fName;
CString FileName;
m_bFlagDlg = FALSE;
CFile Sendfile;
CFileDialog outDlg(TRUE, NULL, NULL, NULL, _T("所有文件 (*.*)|*.*|"), NULL);//设定保存对话框标题
outDlg.m_ofn.lpstrTitle = _T("打开文件");
if(outDlg.DoModal() == IDOK) //显示对话框
{
if(Sendfile.Open(outDlg.GetPathName(), CFile::modeRead/*|CFile::typeBinary*/)) //得到文件名,并用只读方式打开
{
Sendfile.Close();
}
m_bFlagDlg = TRUE;
fName = outDlg.GetPathName();
FileName = outDlg.GetFileName();
}if(m_bFlagDlg == TRUE)
{
int ret;
m_bFlagDlg = FALSE;
clientaddrlen = sizeof(clientaddr);
Client = accept( ServerSocket,(LPSOCKADDR)&clientaddr,&clientaddrlen); nSize = WideCharToMultiByte(CP_THREAD_ACP, 0, FileName.GetBuffer(), -1, NULL, 0,NULL,NULL);
if( nSize > 10240 )
{
nSize = 10240;
}
nSize = WideCharToMultiByte(CP_THREAD_ACP, 0, FileName.GetBuffer(), -1, psText, nSize,NULL,NULL);ret = send( Client, psText, nSize, 0); //发送文件名
if(ret != SOCKET_ERROR )
{
// 发送文件,如果在此处或在SendFileToRemoteRecipient()设断点调试程序,可以正常运行,不设断点的话程序就会进入死循环
SendFileToRemoteRecipient(fName);
}
}}
发送文件:
BOOL CFileTransferDlg::SendFileToRemoteRecipient(CString fName)
{ // local variables used in file transfer
BOOL bRet = TRUE; int fileLength, cbLeftToSend;
sendData = NULL;
CFile sourceFile;
CFileException fe;
BOOL bFileIsOpen = FALSE;
//打开要发送的文件
if( !( bFileIsOpen = sourceFile.Open( fName, CFile::modeRead | CFile::typeBinary, &fe ) ) )
{
bRet = FALSE;
goto PreReturnCleanup;
} // 得到发送文件长度
fileLength = sourceFile.GetLength();
fileLength = htonl( fileLength );
bLeftToSend = sizeof( fileLength );
do
{
int cbBytesSent;
char* bp = (char*)((char*)(&fileLength) + sizeof(fileLength) - cbLeftToSend);
cbBytesSent = send( Client,bp, cbLeftToSend, 0); if ( cbBytesSent == SOCKET_ERROR )
{
bRet = FALSE;
goto PreReturnCleanup;
}
cbLeftToSend -= cbBytesSent;
}
while ( cbLeftToSend>0 );
// send the file's data
sendData = new char[SEND_BUFFER_SIZE];
cbLeftToSend = sourceFile.GetLength();
do
{
int sendThisTime, doneSoFar, buffOffset;
sendThisTime = sourceFile.Read( sendData, SEND_BUFFER_SIZE );
buffOffset = 0;
do
{
doneSoFar = send( Client,sendData + buffOffset, sendThisTime,0 );
if ( doneSoFar == SOCKET_ERROR )
{
bRet = FALSE;
goto PreReturnCleanup;
} buffOffset += doneSoFar;
sendThisTime -= doneSoFar;
cbLeftToSend -= doneSoFar;
}
while ( sendThisTime > 0 );
}
while ( cbLeftToSend > 0 );
PreReturnCleanup:
delete[] sendData;
if ( bFileIsOpen )
sourceFile.Close(); return bRet;
}
接收文件:
void CFileTransferDlg::OnBnClickedButtonRevFile()
{
// TODO: 在此添加控件通知处理程序代码
BOOL bFile = FALSE;
DWORD dwIP = 0;
IN_ADDR ia;
//CString strLocalFileName;
CString strTargetIP;
m_ctlTargetIP.GetAddress(dwIP); //得到IP地址
ia.S_un.S_addr = htonl( dwIP );
strTargetIP = inet_ntoa( ia );
GetIPFromRemoteSender(strTargetIP); //建立和主机连接程序,可以正常连接
bFile = GetFileNameFromRemoteSender(); //接收文件名
if(bFile)
{
bFile = FALSE;
GetFileFromRemoteSender(strLocalFileName); //接收文件
}
}
BOOL CFileTransferDlg::GetFileNameFromRemoteSender() //接收文件名
{
BOOL bRet = FALSE;
CString filename;
int ret;
ret = recv( ClientSoket, msg, sizeof(msg), 0 );
if( ret != SOCKET_ERROR )
{
dwWCharSize = MultiByteToWideChar( CP_ACP, 0, msg, -1, NULL, 0 );
if( dwWCharSize > 10240 )
{
dwWCharSize = 10240;
}
MultiByteToWideChar( CP_ACP, 0, msg, -1, pwText, dwWCharSize );
filename.Format( _T("%s"), pwText); CFileDialog outDlg(FALSE, NULL, filename, NULL, _T("所有文件 (*.*)|*.*|"), NULL);//设定保存对话框标题 outDlg.m_ofn.lpstrTitle = _T("保存文件"); if(outDlg.DoModal() == IDOK) //显示对话框
{
//得到文件名,并用创建和写入方式打开
if(file.Open(outDlg.GetPathName(), CFile::modeCreate|CFile::modeWrite|CFile::typeBinary)) {
strLocalFileName = outDlg.GetPathName();
file.Close();
}
bRet = TRUE;
} }return bRet;
}
BOOL CFileTransferDlg::GetFileFromRemoteSender( CString fName) //接收文件
{ int dataLength, cbBytesRet, cbLeftToReceive;
CFileException fe;
BOOL bFileIsOpen = FALSE;
BOOL bRet = TRUE; char* recdData = NULL; if( !( bFileIsOpen = file.Open( fName,/* CFile::modeCreate| */CFile::modeWrite | CFile::typeBinary, &fe ) ) )
{
bRet = FALSE;
goto PreReturnCleanup;
}
// get the file's size
cbLeftToReceive = sizeof( dataLength ); do
{
char* bp ;
bp =NULL;
bp = (char*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
cbBytesRet = recv(ClientSoket ,bp, cbLeftToReceive,0 ); if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
{
bRet = FALSE;
goto PreReturnCleanup;
}
//data retrieved
cbLeftToReceive -= cbBytesRet; }
while ( cbLeftToReceive > 0 ); dataLength = ntohl( dataLength ); // get the file
recdData = new char[RECV_BUFFER_SIZE];
cbLeftToReceive = dataLength; do
{
int iiGet, iiRecd; iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
iiRecd = recv(ClientSoket ,recdData, iiGet ,0); if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
{ bRet = FALSE;
goto PreReturnCleanup;
}
// data retrieved
file.Write( recdData, iiRecd);
cbLeftToReceive -= iiRecd; }
while ( cbLeftToReceive > 0 );
PreReturnCleanup:
delete[] recdData; if ( bFileIsOpen )
file.Close(); return bRet;}现在遇到的问题是当在发送文件函数里SendFileToRemoteRecipient()设断点调试运行时,程序会正常运行,如果不设断点调试时,接收程序会进入死循环,是怎么回事啊?是哪里出了问题啊?
发文件程序:
void CFileTransferDlg::OnBnClickedButtonSendFile()
{ServerSocket = socket( PF_INET, SOCK_STREAM, 0 ); //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons( usHostPort );if ( bind( ServerSocket,(LPSOCKADDR)&m_sockServerAddr, sizeof(m_sockServerAddr) ) == SOCKET_ERROR ) //与选定的端口绑定
{
MessageBox(_T("无法绑定服务器!"),_T("Socket"), MB_OK|MB_ICONEXCLAMATION);
return;
}if ( listen(ServerSocket,1) == SOCKET_ERROR ) //开始监听客户连接请求
{
MessageBox(_T("服务器监听失败!"),_T("Socket"), MB_OK|MB_ICONEXCLAMATION);
return;
}CString fName;
CString FileName;
m_bFlagDlg = FALSE;
CFile Sendfile;
CFileDialog outDlg(TRUE, NULL, NULL, NULL, _T("所有文件 (*.*)|*.*|"), NULL);//设定保存对话框标题
outDlg.m_ofn.lpstrTitle = _T("打开文件");
if(outDlg.DoModal() == IDOK) //显示对话框
{
if(Sendfile.Open(outDlg.GetPathName(), CFile::modeRead/*|CFile::typeBinary*/)) //得到文件名,并用只读方式打开
{
Sendfile.Close();
}
m_bFlagDlg = TRUE;
fName = outDlg.GetPathName();
FileName = outDlg.GetFileName();
}if(m_bFlagDlg == TRUE)
{
int ret;
m_bFlagDlg = FALSE;
clientaddrlen = sizeof(clientaddr);
Client = accept( ServerSocket,(LPSOCKADDR)&clientaddr,&clientaddrlen); nSize = WideCharToMultiByte(CP_THREAD_ACP, 0, FileName.GetBuffer(), -1, NULL, 0,NULL,NULL);
if( nSize > 10240 )
{
nSize = 10240;
}
nSize = WideCharToMultiByte(CP_THREAD_ACP, 0, FileName.GetBuffer(), -1, psText, nSize,NULL,NULL);ret = send( Client, psText, nSize, 0); //发送文件名
if(ret != SOCKET_ERROR )
{
// 发送文件,如果在此处或在SendFileToRemoteRecipient()设断点调试程序,可以正常运行,不设断点的话程序就会进入死循环
SendFileToRemoteRecipient(fName);
}
}}
发送文件:
BOOL CFileTransferDlg::SendFileToRemoteRecipient(CString fName)
{ // local variables used in file transfer
BOOL bRet = TRUE; int fileLength, cbLeftToSend;
sendData = NULL;
CFile sourceFile;
CFileException fe;
BOOL bFileIsOpen = FALSE;
//打开要发送的文件
if( !( bFileIsOpen = sourceFile.Open( fName, CFile::modeRead | CFile::typeBinary, &fe ) ) )
{
bRet = FALSE;
goto PreReturnCleanup;
} // 得到发送文件长度
fileLength = sourceFile.GetLength();
fileLength = htonl( fileLength );
bLeftToSend = sizeof( fileLength );
do
{
int cbBytesSent;
char* bp = (char*)((char*)(&fileLength) + sizeof(fileLength) - cbLeftToSend);
cbBytesSent = send( Client,bp, cbLeftToSend, 0); if ( cbBytesSent == SOCKET_ERROR )
{
bRet = FALSE;
goto PreReturnCleanup;
}
cbLeftToSend -= cbBytesSent;
}
while ( cbLeftToSend>0 );
// send the file's data
sendData = new char[SEND_BUFFER_SIZE];
cbLeftToSend = sourceFile.GetLength();
do
{
int sendThisTime, doneSoFar, buffOffset;
sendThisTime = sourceFile.Read( sendData, SEND_BUFFER_SIZE );
buffOffset = 0;
do
{
doneSoFar = send( Client,sendData + buffOffset, sendThisTime,0 );
if ( doneSoFar == SOCKET_ERROR )
{
bRet = FALSE;
goto PreReturnCleanup;
} buffOffset += doneSoFar;
sendThisTime -= doneSoFar;
cbLeftToSend -= doneSoFar;
}
while ( sendThisTime > 0 );
}
while ( cbLeftToSend > 0 );
PreReturnCleanup:
delete[] sendData;
if ( bFileIsOpen )
sourceFile.Close(); return bRet;
}
接收文件:
void CFileTransferDlg::OnBnClickedButtonRevFile()
{
// TODO: 在此添加控件通知处理程序代码
BOOL bFile = FALSE;
DWORD dwIP = 0;
IN_ADDR ia;
//CString strLocalFileName;
CString strTargetIP;
m_ctlTargetIP.GetAddress(dwIP); //得到IP地址
ia.S_un.S_addr = htonl( dwIP );
strTargetIP = inet_ntoa( ia );
GetIPFromRemoteSender(strTargetIP); //建立和主机连接程序,可以正常连接
bFile = GetFileNameFromRemoteSender(); //接收文件名
if(bFile)
{
bFile = FALSE;
GetFileFromRemoteSender(strLocalFileName); //接收文件
}
}
BOOL CFileTransferDlg::GetFileNameFromRemoteSender() //接收文件名
{
BOOL bRet = FALSE;
CString filename;
int ret;
ret = recv( ClientSoket, msg, sizeof(msg), 0 );
if( ret != SOCKET_ERROR )
{
dwWCharSize = MultiByteToWideChar( CP_ACP, 0, msg, -1, NULL, 0 );
if( dwWCharSize > 10240 )
{
dwWCharSize = 10240;
}
MultiByteToWideChar( CP_ACP, 0, msg, -1, pwText, dwWCharSize );
filename.Format( _T("%s"), pwText); CFileDialog outDlg(FALSE, NULL, filename, NULL, _T("所有文件 (*.*)|*.*|"), NULL);//设定保存对话框标题 outDlg.m_ofn.lpstrTitle = _T("保存文件"); if(outDlg.DoModal() == IDOK) //显示对话框
{
//得到文件名,并用创建和写入方式打开
if(file.Open(outDlg.GetPathName(), CFile::modeCreate|CFile::modeWrite|CFile::typeBinary)) {
strLocalFileName = outDlg.GetPathName();
file.Close();
}
bRet = TRUE;
} }return bRet;
}
BOOL CFileTransferDlg::GetFileFromRemoteSender( CString fName) //接收文件
{ int dataLength, cbBytesRet, cbLeftToReceive;
CFileException fe;
BOOL bFileIsOpen = FALSE;
BOOL bRet = TRUE; char* recdData = NULL; if( !( bFileIsOpen = file.Open( fName,/* CFile::modeCreate| */CFile::modeWrite | CFile::typeBinary, &fe ) ) )
{
bRet = FALSE;
goto PreReturnCleanup;
}
// get the file's size
cbLeftToReceive = sizeof( dataLength ); do
{
char* bp ;
bp =NULL;
bp = (char*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
cbBytesRet = recv(ClientSoket ,bp, cbLeftToReceive,0 ); if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
{
bRet = FALSE;
goto PreReturnCleanup;
}
//data retrieved
cbLeftToReceive -= cbBytesRet; }
while ( cbLeftToReceive > 0 ); dataLength = ntohl( dataLength ); // get the file
recdData = new char[RECV_BUFFER_SIZE];
cbLeftToReceive = dataLength; do
{
int iiGet, iiRecd; iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
iiRecd = recv(ClientSoket ,recdData, iiGet ,0); if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
{ bRet = FALSE;
goto PreReturnCleanup;
}
// data retrieved
file.Write( recdData, iiRecd);
cbLeftToReceive -= iiRecd; }
while ( cbLeftToReceive > 0 );
PreReturnCleanup:
delete[] recdData; if ( bFileIsOpen )
file.Close(); return bRet;}现在遇到的问题是当在发送文件函数里SendFileToRemoteRecipient()设断点调试运行时,程序会正常运行,如果不设断点调试时,接收程序会进入死循环,是怎么回事啊?是哪里出了问题啊?
---------------------
这个函数里两个do--while循环????
系统进入死循环是在:接收文件时
do
{
char* bp ;
bp =NULL;
bp = (char*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
cbBytesRet = recv(ClientSoket ,bp, cbLeftToReceive,0 ); //在此处进入死循环 if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
{
int iErr = ::GetLastError();
TRACE( "GetFileFromRemoteSite returned a socket error while getting file length\n"
"\tNumber of Bytes received (zero means connection was closed) = %d\n"
"\tGetLastError = %d\n", cbBytesRet, iErr ); bRet = FALSE;
goto PreReturnCleanup;
}
cbLeftToReceive -= cbBytesRet;}
while ( cbLeftToReceive > 0 );
bp =NULL;
bp = (char*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;这是做什么呢?你是要分配内存么?
#define PF_INET AF_INET