如何使用Winsock2处理短读取?

时间:2013-03-02 20:26:04

标签: c++ winsock2

我在使用带有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

我该怎么做才能处理这些错误和奇怪的角色?

2 个答案:

答案 0 :(得分:0)

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

这一行 - buf = new char[1024]; - 显然存在问题,可能导致服务器崩溃,因为内存不足。没有清理工作。首先添加相应的delete语句,最好放在send调用之后。如果这不能解决问题,我会使用一个小的测试文件并在服务器代码中逐步执行while循环。

P.S。比在循环中使用newdelete更好的解决方案是重用现有的buff。编译器可能会优化此错误,但如果不是,则会严重阻碍应用程序性能。我认为你实际上应该只将buf = new char[1024];移到循环之外。 buf是一个字符指针,因此如果您传递readbuf将继续覆盖buf的内容。一遍又一遍地重新分配缓冲区并不好。

关于错误MSDN说:

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

答案 1 :(得分:-1)

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

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

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

还有一篇关于这里的文章,你可能想看一下:

socket error 10054

祝你好运!