本人最近使用C++ socket技术实现传递文件的功能,但是文件总是还没有传送完成,接收方就recv返回0,看了recv的说明,按道理讲应该是接收完毕才会返回0,但是我这文件还没收完呢,怎么就返回0了呢,不是说TCP协议是能保证通讯的正确性的吗,无奈,到网上找了一个别人写的传递文件的代码,发现在接收方收完一个小包(文件是拆分成一个个小包传递的)之后,会再给服务方发送一个反馈,而发送方则会调用recv等待这个反馈,等到反馈之后再发送下一个小包,就这样,实现了文件的正常传输,我不由得疑惑,TCP的正确性是这样让我们自己来保证完整性的啊。。。。
下面是codeproject上的一个传递文件的示例WSFileTransfer代码节选,
void WComm::fileReceive(char *filename)
{
char rec[50] = "";
recv( m_socket, filename, 32, 0 );
send( m_socket, "OK", strlen("OK"), 0 );
FILE *fw = fopen(filename, "wb");
int recs = recv( m_socket, rec, 32, 0 );
send( m_socket, "OK", strlen("OK"), 0 );
rec[recs]='\0';
int size = atoi(rec);
while(size > 0)
{
char buffer[1030];
if(size>=1024)
{
recv( m_socket, buffer, 1024, 0 );
send( m_socket, "OK", strlen("OK"), 0 );
fwrite(buffer, 1024, 1, fw);
}
else
{
recv( m_socket, buffer, size, 0 );
send( m_socket, "OK", strlen("OK"), 0 );
buffer[size]='\0';
fwrite(buffer, size, 1, fw);
}
size -= 1024;
}
fclose(fw);
}
void WComm::fileSend(char *fpath)
{
// Extract only filename from given path.
char filename[50];
int i=strlen(fpath);
for(;i>0;i--)if(fpath[i-1]=='\\')break;
for(int j=0;i<=(int)strlen(fpath);i++)filename[j++]=fpath[i];
ifstream myFile (fpath, ios::in|ios::binary|ios::ate);
int size = (int)myFile.tellg();
myFile.close();
char filesize[10];itoa(size,filesize,10);
send( m_socket, filename, strlen(filename), 0 );
char rec[32] = "";recv( m_socket, rec, 32, 0 );
send( m_socket, filesize, strlen(filesize), 0 );
recv( m_socket, rec, 32, 0 );
FILE *fr = fopen(fpath, "rb");
while(size > 0)
{
char buffer[1030];
if(size>=1024)
{
fread(buffer, 1024, 1, fr);
send( m_socket, buffer, 1024, 0 );
recv( m_socket, rec, 32, 0 );
}
else
{
fread(buffer, size, 1, fr);
buffer[size]='\0';
send( m_socket, buffer, size, 0 );
recv( m_socket, rec, 32, 0 );
}
size -= 1024;
}
fclose(fr);
}