0

我在使用 Windows 的 Winsock2 通过网络接收数据时遇到问题。我正在尝试使用简单的客户端和服务器系统来实现文件传输程序。使用我们当前的代码,最后进来的数据包不会附加到文件中,因为它不是缓冲区的大小。因此,文件传输并不完全,会引发错误并中断。它并不总是最后一个数据包,有时它更早。

这是服务器代码的片段:

int iResult;
ifstream sendFile(path,  ifstream::binary);
char* buf;

if (sendFile.is_open()) {
printf("File Opened!\n");
// Sends the file
while (sendFile.good()) {
    buf = new char[1024];
    sendFile.read(buf, 1024);
    iResult = send(AcceptSocket, buf, (int)strlen(buf)-4, 0 );
    if (iResult == SOCKET_ERROR) {
        wprintf(L"send failed with error: %d\n", WSAGetLastError());
        closesocket(AcceptSocket);
        WSACleanup();
        return 1;
    }
    //printf("Bytes Sent: %d\n", iResult);
}
sendFile.close();

}

这是客户端代码的片段:

int iResult;
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN] = "";

do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0){
        printf("%s",recvbuf);
        myfile.write(recvbuf, iResult);
    }
    else if ( iResult == 0 ) {
        wprintf(L"Connection closed\n");
    } else {
        wprintf(L"recv failed with error: %d\n", WSAGetLastError());
    }

} while( iResult > 0 );

myfile.close();

尝试传输作为字典的文件时,它可能会随机中断。例如,一个运行在 S 的早期中断并在末尾附加了奇怪的字符,这并不罕见:

...
sayable
sayer
sayers
sayest
sayid
sayids
saying
sayings
╠╠╠╠╠╠╠╠recv failed with error: 10054

我能做些什么来处理这些错误和奇怪的字符?

4

2 回答 2

0

错误发生在服务器端。您收到“对等方重置连接”错误。

这条线 - buf = new char[1024];- 显然是有问题的,并且很可能导致服务器崩溃,因为它耗尽了内存。没有清理发生。首先添加适当的delete语句,最好放在send调用之后。如果那不能解决它,我将使用一个小测试文件并逐步执行服务器代码中的 while 循环。

PS 比在循环中使用newand更好的解决方案delete是重用现有的 buff。编译器可能会优化这个错误,但如果不是这样,你就会严重阻碍应用程序的性能。我认为您实际上应该移出buf = new char[1024];循环。buf是一个 char 指针,所以如果你传递它read,它将继续覆盖它的内容。一遍又一遍地重新分配缓冲区是不好的。bufbuf

关于错误 MSDN 说:

现有连接被远程主机强行关闭。如果远程主机上的对等应用程序突然停止,主机重新启动,主机或远程网络接口被禁用,或者远程主机使用硬关闭,这通常会导致(有关远程主机上 SO_LINGER 选项的更多信息,请参阅 setsockopt插座)。如果在一个或多个操作正在进行时,由于保活活动检测到故障而导致连接中断,则也可能导致此错误。正在进行的操作因 WSAENETRESET 而失败。后续操作因 WSAECONNRESET 而失败。

于 2013-03-02T20:40:28.347 回答
-1

首先,在循环中使用new运算符可能不好,尤其是没有相应的delete。我不是 C++ 专家,虽然(只有 C)但我认为值得检查。

其次,套接字错误 10054 是“对等连接重置”,它告诉我服务器没有在套接字上执行所谓的正常关闭。通过优雅关闭,WinSock 将等到对方接收到所有待处理的数据,然后再发送中断连接的 FIN 消息。您的服务器很可能只是在将最终缓冲区提供给 WinSock 后立即关闭,而没有任何时间进行传输。您需要查看SO_LINGER套接字选项——它们解释了优雅关闭与非优雅关闭。

简单来说,要么需要在连接中添加自己的协议,以便客户端可以确认收到最终数据块,要么服务器端需要调用setsocketopt()设置SO_LINGER超时,以便 WinSock 等待来自 TCP/IP 的确认客户端在通过网络发出套接字关闭之前的最后一个数据块。如果你不做这些事情中的至少一件,那么就会出现这个问题。

您可能还想查看另一篇关于此的文章:

套接字错误 10054

祝你好运!

于 2013-03-02T20:41:43.153 回答