我在发送端写的while循环来发送文件,代码基本如下:
void CMySocket::SendFile()
{
CString ip("127.0.0.1") ;
CString cFilePathName ; CString filter("txt(*.txt)|*.txt|avi(*.avi)|*.avi|*.*") ; //用于指定对话框打开的文件类型

CFileDialog *fileDialog = new CFileDialog(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,filter,NULL); if(IDOK == fileDialog->DoModal())
{
cFilePathName = fileDialog->GetPathName(); //获取路径包括文件名
} CFile cFile((LPCTSTR)cFilePathName,CFile::modeRead|CFile::typeBinary); //根据指定的路径获取文件

//文件的缓冲区大小
//fileSize + '$' + pathSize + '$' + cFilePathName + '\0' ;
int msgSize = 0 ;
char * fileMsg = new char[BUFFER_SIZE];

int file_len = (int)cFile.GetLength(); //文件的大小
int leftToSend = file_len ;
while (file_len>0)
{
fileMsg[msgSize++] = char(file_len%10+48) ;
file_len /= 10 ;
}

fileMsg[msgSize++] = '$' ; int path_len = cFilePathName.GetLength() ;
while (path_len>0)
{
fileMsg[msgSize++] = char(path_len%10+48) ;
path_len /= 10 ;
} fileMsg[msgSize++] = '$' ; int len = (int)cFilePathName.GetLength() ;
for(unsigned i = 0 ; i < len ; ++ i )
{
fileMsg[msgSize++] = cFilePathName[i] ;
} fileMsg[msgSize] = '\0' ; //先发送文件信息

if ( 0 == conn.Send(fileMsg,msgSize) )
return ; delete []fileMsg ; //开始进入发送文件内容的部分 char * sendBuf = new char[BUFFER_SIZE] ; int readSize , sendSize ; do
{
readSize = (leftToSend>BUFFER_SIZE) ? BUFFER_SIZE : leftToSend ;
sendSize = cFile.Read(sendBuf,readSize) ; conn.Send(sendBuf,sendSize) ; leftToSend -= BUFFER_SIZE ;
}
while (leftToSend>0) ; delete []sendBuf ;
cFile.Close();
conn.Close() ;}
我的接收代码是在OnReceive这个函数中的,由于每次来数据都会触发OnReceive这个函数,所以就免了一个while循环(也不知道我说的对不对),这样我的OnReceive()代码如:void CMySocket::OnConnet(int nErrorCode)
{
if (nErrorCode==0)
{
AfxMessageBox(_T("Client port OnConnet() function is running well!")) ;
}
else
{
AfxMessageBox(_T("Client port OnConnect() function is running , but something error happen!")) ;
}
CAsyncSocket::OnConnect(nErrorCode) ;
}void CMySocket::OnReceive(int nErrorCode)
{
if (0==nErrorCode )
{
//AfxMessageBox(_T("Client port OnReceive() is running well!")) ;
//AfxMessageBox(_T("Client port RecvFile() run already!")) ;
//if ( flag )
//{
// RecvFile() ;
// flag = false ;
//}

char * recvBuf = new char[BUFFER_SIZE] ;
int getRecv , getSize  ; if (0==leftToRecvSize)
{
getRecv = this->Receive(recvBuf,BUFFER_SIZE) ;

//file_len + filePathName.size() + filePathName
//int + '$' + int + '$' + CString
//解析file_len
int len = 0 , point = 0 ; //point指向recvBuf的指针位置
int t = 1 ;
for ( point = 0 ; recvBuf[point] != '$' && point < getRecv ; ++ point )
{
len += (recvBuf[point] - '0') * t ;
t *= 10 ;
}
int fileSize = len ;
//解析filePathName.size()
len = 0 , t = 1 ; //继续用len来解析
++ point ; //让point指向下一个int
for ( ; recvBuf[point] != '$' && point < getRecv ; ++ point )
{
len += (recvBuf[point] - '0') * t ;
t *= 10 ;
}
//解析filePathName
++ point ; //让point来指向CString cFilePathName
recvBuf[getRecv] = '\0' ;
CString str(recvBuf+point,len) ; //解析fileName
CString cFileName = getFileName(str) ;
CString cFilePathName = _T("D:\\khd\\")+cFileName ; leftToRecvSize = fileSize ; if ( ! mFile.Open(cFilePathName,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary) )
{
AfxMessageBox(_T("读取")+cFilePathName+_T("文件错误!")) ;
} getRecv -= len+point ;
if (getRecv > 0)
{
mFile.Write(recvBuf+len+point,getRecv) ;
}
leftToRecvSize -= getRecv ;
} getSize = ((leftToRecvSize>BUFFER_SIZE) ? BUFFER_SIZE : leftToRecvSize) ;
getRecv = this->Receive(recvBuf,getSize) ; if (getRecv == SOCKET_ERROR )
{
AfxMessageBox(_T("数据接收失败了!")) ;
delete []recvBuf ;
return ;
} mFile.Write(recvBuf,getRecv) ;
leftToRecvSize -= getRecv ;

}
else
{
AfxMessageBox(_T("Client port OnReceive() is running , but something error happen!")) ;
}
CAsyncSocket::OnReceive(nErrorCode) ;
}我在调试的时候发现发送的时候是都发送了,leftToSend这个真的为0了,但在Receive这里leftToRecvSize不为0时就接收不到数据了,这是为什么呢?可能我在哪里出错了呢?

解决方案 »

  1.   

    你看看receive的返回值,GetLastError看看是报什么错。
    还有,你那个接收缓冲recvBuf ,每次调用onReceive时都会new一个出来,可是只有接收数据失败时你才delete掉,应该在用完后都释放的
      

  2.   

    Receive()的返回值是接到数据的字节数,每次执行Receive的时候都会有一个大于0的值,一般都是缓冲区的大小4096,但是当接收不完的时候OnReceive这个函数就不执行了,我不知道为什么!!
      

  3.   

    做一个小的延时,如果在线程里的话,可以Sleep(10).
      

  4.   

    我接收的缓冲区设为了40960,之后每次发送4096,这样就搞定了,之后Sleep(1)了一下,就搞定了@
    谢谢大家了