如何解决非阻塞recv上奇怪的win sock bug
这是我的非重叠套接字的接收文件功能。
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[]
混在一起了。因此,循环不会中断。仍然不明白为什么它可以在开发机器上工作。无论如何,正如预期的那样,问题不在我在此问题中发布的代码中。谢谢你们!
解决方案是在睡眠较少的情况下发送数据。 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。