使用套接字一次发送整个数据

时间:2013-03-01 14:11:15

标签: c++ sockets winsock winsock2

我尝试使用winsock2 lib从客户端向服务器发送文件。

将文件转换为char数组后,我使用send()命令发送此数组。

问题:单独发送的数据。

例如:我的文件大小:144429。 它不会立即发送,数据被分成许多部分,例如: 先发送:1460

第二次发送:21544

第三次发送:57136

等。

直到发送完整数据。

所以我的问题是:是什么原因导致它按部件发送而不是一次发送????

解决方案我发现工作但没有任何意义: 如果我正在添加

  

cout<< " bla bla bla&#34 ;;

在send()函数之前,它确实有效并且一次发送整个144429。 (但是如果给cout的字符串更短,没有变化,则按部分发送)

CODE:

客户端

int Client::sendData(char *sendbuf, int length)
{   
    int iResult;

    // if I remove those next few lines (until and including the cout line)
    // the send will split.
    char tmp[1];
    // sent 1 dummy byte
    iResult = send( _connectSocket, tmp, 1, 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }
    cout << "SENDING DATA..." << endl;

    // THIS IS THE RELEVANT AND ACTUAL DATA I WANT TO SEND
    // send the data
    iResult = send( _connectSocket, sendbuf, length, 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }

    cout << "Data sent (" << iResult << " Bytes)" << endl;

    return 0;

}

服务器端:

    char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int iResult = 0;
int totalBytesRead = 0;

// Receive until the peer shuts down the connection
do {
    totalBytesRead += iResult;
    iResult = recv(_clientSocket, recvbuf, recvbuflen, 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);

// store data into file
FileTransfer::binaryToFile(recvbuf, "doch.docx", totalBytesRead-1);

return 0;

}

2 个答案:

答案 0 :(得分:3)

无法保证send将某些数据作为一个单元传输 - 它只是不起作用。你必须添加一些额外的信息来告诉系统“这里有这么多数据”和/或“我现在已经完成了”。即使您可以说服您的发送方在一个数据包中发送所有内容,假设接收方没有直接连接只需要一条简单的电缆连接到发送方,您就无法保证数据包在通过期间不会被分解通过网络。

您必须接受如果您在数据包中发送多个字节,则可能需要多次调用send。为了简化它,编写一个函数,它采用任意大小的“整个数据包”,并根据需要多次调用发送...如果你有一个协议,指示发送的数据的大小[如在前几个字节] ,你可以有一个接收功能,做同样的事情。

答案 1 :(得分:2)

根据您使用的套接字类型,底层传输协议中的数据大小可能存在限制。

如果您使用网络套接字,则大小受最大传输单位的限制(请参阅:http://en.wikipedia.org/wiki/Maximum_transmission_unit)。

如果您的数据不适合此大小,则必须循环迭代发送部分数据,直到发生错误或所有数据都已发送为止。