问题描述
HANDLE recvfile = CreateFile(fileinfo[0],FILE_APPEND_DATA,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_norMAL,NULL);
if (recvfile == INVALID_HANDLE_VALUE) {
sockprintf(sockfd,"[Error Creating File] : %ld",GetLastError());
}
else {
memset(recvbuf,'\0',BUFFER); // Clear main buffer
int total = 0; // Total bytes received
// set_blocking_mode(sockfd,FALSE);
do{ // IF Total is equal to expected bytes. Break the loop,And stop receiving.
fsize = recv(sockfd,recvbuf,BUFFER,0); // Receive file
if (fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = FALSE;
printf("[X] Connection interrupted while receiving file %s for %s size.",fileinfo[0],fileinfo[1]);
}
write = WriteFile(recvfile,fsize,&dwBytesWritten,NULL); // Write file data to file
total += fsize; // Add number of bytes received to total.
} while(total != expected);
// set_blocking_mode(sockfd,TRUE);
if (write == FALSE)
{
sockprintf(sockfd,"[Error Writing file %s of %s size] Error : %ld.",fileinfo[1],GetLastError());
}
else {
sockprintf(sockfd,"\n[ Received File : %s ]\n[ File Size : %s bytes ]\n[ Bytes written : %ld ]\n",dwBytesWritten);
}
CloseHandle(recvfile);
}
这很好用!文件传输几乎是即时的,没有错误或缓冲区损坏。 我在Visual Studio 2019上。问题是,当我编译可执行文件并将其移至测试虚拟机时。程序崩溃。在Windows 10和Windows 7上进行了测试。
崩溃发生在do while循环上。该程序不会中断。我尝试使用msvc(最新)以及mingw-w64和tdm gcc进行编译。错误是相同的。 该代码只能在我自己的机器上运行,而不能在其他任何机器上运行。
解决方法
您需要检查的不只是WSAECONNRESET。几乎每个错误(在非阻塞状态下保存为“ would block”)都是致命的,指示套接字应中止。不要忘记recv
可以并且将0
返回,如果远程端优雅地关闭其末端。
整个循环:
do{ // IF Total is equal to expected bytes. Break the loop,And stop receiving.
fsize = recv(sockfd,recvbuf,BUFFER,0); // Receive file
if (fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = FALSE;
printf("[X] Connection interrupted while receiving file %s for %s size.",fileinfo[0],fileinfo[1]);
}
write = WriteFile(recvfile,fsize,&dwBytesWritten,NULL); // Write file data to file
total += fsize; // Add number of bytes received to total.
} while(total != expected);
应该是:
do{
fsize = recv(sockfd,0); // Receive file
if (fsize == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
// ISSUE SELECT CALL HERE TO WAIT FOR MORE DATA
}
else {
// FATAL ERROR - abort
break;
}
}
else if (fsize == 0) {
break; // remote connection terminated cleanly.
}
else {
write = WriteFile(recvfile,NULL);
total += fsize;
}
} while(total != expected);
,
我已经解决了该问题,IT似乎是我自己的无知,服务器端提供文件信息的速度过快,因此fileinfo[]
混在一起了。因此,循环不会中断。仍然不明白为什么它可以在开发机器上工作。无论如何,正如预期的那样,问题不在我在此问题中发布的代码中。谢谢你们!
解决方案是在睡眠较少的情况下发送数据。 :)