如何使用 C++ 在 Winsock 中将大字符串从客户端发送到服务器

Posted

技术标签:

【中文标题】如何使用 C++ 在 Winsock 中将大字符串从客户端发送到服务器【英文标题】:How send big string in winsock using c++ from client to server 【发布时间】:2019-11-07 15:55:23 【问题描述】:

我正在使用 C++ 中的 Winsock 编写一个服务器-客户端应用程序,用于逐行发送文件,但在发送大字符串时遇到问题。线条非常大。

为了让服务器从客户端获取消息,我使用下面的代码。

int result;
char message[200];

while (true)

    recv(newSd, (char*)&message, sizeof(message), 0);

    cout << "The Message from client: " << message << ";";

如果我发送短消息,上面的代码可以正常工作。但是,我想要的是在文件中发送未知大小的行。

如何发送一个未知的大string而不是char message[200];

【问题讨论】:

您是否考虑过使用 std::vector&lt;char&gt;std::vector&lt;std::byte&gt; 之类的东西来代替固定大小的 C 样式数组? 你得到的结果是碎片吗? @JesperJuhl 但我看到 recv 函数定义低于我必须传递一种 char * 的位置。 WINSOCK_API_LINKAGE int PASCAL recv (SOCKET, char *, int, int);不确定,当我将消息声明为 stringvector 时如何传递 char * 类型 @swamybabun std::vector::data(), std::string::c_str(). How to send a big unknown string 而不是 char message[200]; -- 另一个问题是您不会以这种方式使用 recv向我们展示。您需要循环 recv 直到它是 &lt;=0,连接到现有字符串。 【参考方案1】:

TCP 是一个字节流,它对消息或行或类似的东西一无所知。当您通过 TCP 发送数据时,它所知道的只是原始字节,而不是字节代表的内容。您有责任在 TCP 之上实现消息传递协议,以某种有意义的方式分隔数据,以便接收者知道数据何时完成。有两种方法可以做到这一点:

在发送实际数据之前发送数据长度。接收方先读取长度,然后读取长度表示的字节数。

在发送数据后发送一个唯一的终止符。确保终止符永远不会出现在数据中。然后接收器可以读取,直到接收到终止符。

您没有在 recv() 代码中处理其中任何一个,所以我怀疑您也没有在 send() 代码中处理它们中的任何一个(您没有显示)。

由于您发送的是文本文件,因此您可以:

发送文件大小,例如uint32_tuint64_t(取决于文件的大小),然后发送原始文件字节。

按原样单独发送每个文本行,在每行之后以CRLFbare-LF 换行符终止,然后在最后一行之后发送最终终止符。

您还忽略了recv() 的返回值,它告诉您实际收到了多少字节。它可以并且通常确实返回比请求更少的字节,因此您必须准备好多次调用recv(),通常在一个循环中,以完全接收数据。与send() 相同。

【讨论】:

以上是关于如何使用 C++ 在 Winsock 中将大字符串从客户端发送到服务器的主要内容,如果未能解决你的问题,请参考以下文章

如何检查客户端是不是通过 C++ 中的 Winsock 断开连接?

C++ Winsock API如何在接受连接之前获取连接客户端IP?

如何在 C++ 中将字符串转换为字符? [复制]

如何在 C++ 中将数字转换为字符串,反之亦然

如何使用 stringstream 在 C++ 中将字符串转换为双精度值 [关闭]

C++ Winsock P2P