【问题标题】:sending whole data at once using socket使用套接字一次发送整个数据
【发布时间】:2013-02-16 01:43:15
【问题描述】:

我正在尝试使用 winsock2 lib 将文件从客户端发送到服务器。

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

问题:单独发送的数据。

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

第二次发送:21544

第三次发送:57136

等等。

直到全部数据发送完毕。

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

我发现可行但没有任何意义的解决方案: 如果我要添加

cout

在 send() 函数之前,它确实工作并一次发送整个 144429。 (但如果给 cout 的字符串较短,则不改变,分部发送)

代码:

客户端

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;

}

【问题讨论】:

  • 重新标记为 C++。是的,一些代码就可以了。
  • sendbuf 是否以空值终止?换句话说,指针指向的数据的大小在 int Client::sendData() 的范围内是否已知?
  • @Kevin 是的,大小是已知的,并作为参数-int 长度给出。

标签: c++ sockets winsock winsock2


【解决方案1】:

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

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

如果您的数据不适合此大小,您将不得不在循环中迭代发送部分数据,直到发生错误或发送所有数据。

【讨论】:

  • 我知道总是有一个限制,但在这种情况下,我已经成功地立即发送数据,并使用初步发送命令和 cout(为什么它有效?我不知道..)跨度>
【解决方案2】:

无法保证send 将某些数据作为一个单元传输——它只是不能那样工作。你必须添加一些额外的信息来告诉系统“这里有这么多数据”和/或“我现在完成了”。即使你可以说服你的发送方在一个数据包中发送所有内容,假设接收方没有直接通过一根简单的电缆连接到发送方,你也不能保证数据包在传递过程中没有被分解通过网络。

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

【讨论】:

  • +1,是的 - 不断重复的“我想通过流媒体服务发送大于一个字节的消息”。
  • +1 这也意味着最初读取整个文件而不是字节数组的努力是浪费时间和空间。使用合理大小的缓冲区,只需读取和写入缓冲区加载直到流结束。您可以看到超过 4-8k 的缓冲区也毫无意义。
猜你喜欢
  • 2012-04-26
  • 1970-01-01
  • 2015-01-23
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 2017-07-13
  • 1970-01-01
  • 2012-07-17
相关资源
最近更新 更多