自己写了一个收发文件的程序:
发文件程序:
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()设断点调试运行时,程序会正常运行,如果不设断点调试时,接收程序会进入死循环,是怎么回事啊?是哪里出了问题啊?

解决方案 »

  1.   

    BOOL CFileTransferDlg::GetFileFromRemoteSender( CString fName) //接收文件
    ---------------------
    这个函数里两个do--while循环????
      

  2.   

    而且循环里都有recv接收操作?
      

  3.   

    补充点内容:
    系统进入死循环是在:接收文件时
    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 );
      

  4.   

    char* bp ;
    bp =NULL;
    bp = (char*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;这是做什么呢?你是要分配内存么?
      

  5.   


    #define PF_INET         AF_INET