Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ winsock recv()重复/丢失数据_C++_Sockets_Winsock_Recv - Fatal编程技术网

C++ winsock recv()重复/丢失数据

C++ winsock recv()重复/丢失数据,c++,sockets,winsock,recv,C++,Sockets,Winsock,Recv,我正在编写一个简单的服务器/客户端程序,将文件从客户端发送到服务器。 我正在使用winsock2。我将每次发送数据的容量限制为5000 客户端发送: 在服务器端recv上: 问题是: 在运行客户端和服务器并发送文件后,它确实会显示发送/接收的正确数据大小,当然是以字节为单位的文件大小,但输出文件不同,当我用一些文本编辑器notepad++打开它时,我可以清楚地看到输出文件包含的数据较少,但是file->Properties显示的文件大小相同,并且一些数据是重复的 我的问题: revc是如何工作的

我正在编写一个简单的服务器/客户端程序,将文件从客户端发送到服务器。 我正在使用winsock2。我将每次发送数据的容量限制为5000

客户端发送:

在服务器端recv上:

问题是:

在运行客户端和服务器并发送文件后,它确实会显示发送/接收的正确数据大小,当然是以字节为单位的文件大小,但输出文件不同,当我用一些文本编辑器notepad++打开它时,我可以清楚地看到输出文件包含的数据较少,但是file->Properties显示的文件大小相同,并且一些数据是重复的

我的问题:

revc是如何工作的?如果它在许多调用中接收数据,它是否会将数据累积到缓冲区中?在我的例子中:recvbuf还是重写缓冲区? 据我所知,它是累积的,所以我的代码是正确的


谢谢

我看不出你在写什么。每次调用recv时,它都会覆盖recvbuf中已有的内容。因此,在已注释掉接收到的数据打印的地方,您应该复制要保留在缓冲区之外的数据。

我看不出您正在从recvbuf中写入什么。每次调用recv时,它都会覆盖recvbuf中已有的内容。因此,如果已注释掉接收到的数据打印,则应复制要保留在缓冲区之外的数据。

代码中存在几个问题

客户端:

在这里,您永远不会更新数据来说明已经发送的字节,因此每次调用send时,它都会一次又一次地发送相同的数据,即数据缓冲区的第一个MAX_TRANSIT_SIZE字节。快速修复,假设数据是指向任何字节类型uint8\u t、char、。。。将是:

发送连接插座,数据+总字节数,最大传输大小,0

您还应该限制发送的数据大小,因为除非长度最初是MAX_TRANSIT_size的倍数,否则在到达数据末尾时,缓冲区将溢出:

发送连接插座,数据+总字节数,标准::最小长度,最大传输大小,0

服务器端:

就像send一样,recv不知道我在缓冲区中已经收到了什么。因此,每次调用recv时,它都会将接收到的新数据放在缓冲区的开头,覆盖旧数据。这可能是您想要的,也可能不是您想要的,这很难说,因为您没有向我们展示如何使用该缓冲区。您可能希望使用与我刚才解释的发送缓冲区相同的方法来管理接收缓冲区。
代码中有几个问题

客户端:

在这里,您永远不会更新数据来说明已经发送的字节,因此每次调用send时,它都会一次又一次地发送相同的数据,即数据缓冲区的第一个MAX_TRANSIT_SIZE字节。快速修复,假设数据是指向任何字节类型uint8\u t、char、。。。将是:

发送连接插座,数据+总字节数,最大传输大小,0

您还应该限制发送的数据大小,因为除非长度最初是MAX_TRANSIT_size的倍数,否则在到达数据末尾时,缓冲区将溢出:

发送连接插座,数据+总字节数,标准::最小长度,最大传输大小,0

服务器端:

就像send一样,recv不知道我在缓冲区中已经收到了什么。因此,每次调用recv时,它都会将接收到的新数据放在缓冲区的开头,覆盖旧数据。这可能是您想要的,也可能不是您想要的,这很难说,因为您没有向我们展示如何使用该缓冲区。您可能希望使用与我刚才解释的发送缓冲区相同的方法来管理接收缓冲区。
你确定每次都是覆盖吗??因为在VS2010调试器中,我可以看到它包含相同的数据,前几个字节是一个带有null terminator的字符串,所以调试器一直显示到\0,并且我正在代码中的其他地方使用缓冲区:fileData*fData=FileTransfer::deserializeFileDatarecvbuf;非常确定:你确定每次都是覆盖吗??因为在VS2010调试器中,我可以看到它包含相同的数据,前几个字节是一个带有null terminator的字符串,所以调试器一直显示到\0,并且我正在代码中的其他地方使用缓冲区:fileData*fData=FileTransfer::deserializeFileDatarecvbuf;非常肯定:谢谢你提供了信息丰富的答案。我将尝试解释如何处理传输:在客户端:我将文件二进制流读入char数组,然后将其发送到服务器。在服务器端:我从客户端接收代表文件的字符数组,并将其写入磁盘。感谢您提供的信息性回答。我将尝试解释如何处理传输:在客户端:我将文件二进制流读入char数组,然后将其发送到服务器。在服务器端:我从客户端接收代表文件的char数组,并将其写入磁盘。
int iResult = 0;
int totalBytesSent = 0;

while (length > 0){
    iResult = send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 ); // MAX_TRANSIT_SIZE is 5000
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }
    totalBytesSent += iResult;
    length -= iResult;
    //cout << "Data sent (" << iResult << " Bytes)" << endl;
}
cout << "Total Bytes Sent: (" << totalBytesSent << ")" << endl;

return 0;
    // Receive and send data
char recvbuf[MAX_DATA_SIZE];

int iResult = 0;
int totalBytesRead = 0;

// Receive until the peer shuts down the connection

do {
    totalBytesRead += iResult;
    iResult = recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);

    if (iResult > 0) {
        //printf("RECEIVED DATA\n");
        //printf("Bytes received: %d\n", iResult);

    } else if (iResult == 0)
        printf("Connection closing...\n");
    else {
        printf("recv failed: %d\n", WSAGetLastError());
        closesocket(_clientSocket);
        WSACleanup();
        return 1;
    }

} while (iResult > 0);

cout << "Total Bytes Received: (" << totalBytesRead << ")" << endl;
send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 );
recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);