5

我正在尝试在 C++ 中使用一些套接字网络编程。我正在尝试发送文本“Hello World!” 使用 C++ send() 函数发送到服务器。起初,我将缓冲区的大小设置为 13,因为“Hello World!” 一共是 12 个字符(你必须使它比字符数多一个)。如果我发送大约 7 次,发送功能只会将字符发送到服务器。当它最终到达服务器时,它看起来像这样:

“你好世界!你好世界!你好世界!你好世界!你好世界!你好世界!你好世界!”

现在这是有趣的部分。“你好世界!” 如果我将缓冲区大小设置为 256 (char buffer[256];),句子会立即发送。但是,当涉及到这样的服务器时,它会显示“Hello World!” 这两个词后面有一大堆空格。为什么会发生这种情况,如果可能,我该如何解决?请告诉我。

谢谢

4

5 回答 5

7

当您使用缓冲区调用read(or receive) 以从套接字读取时,将返回一个整数值,该值指定读取的字节数。您应该只从缓冲区中获取那么多。其余的无关紧要:

int count = read(...);
// buffer[0 .. count - 1] contains the appropriate data.
于 2009-04-15T00:36:25.790 回答
6

Nagle 算法通常默认开启。这会将几个小数据包合并为一个。关闭 Nagle 的算法将允许立即发送小数据包。

于 2009-04-15T01:21:44.620 回答
4

在您准备好发送数据之前,存在缓冲区来存储数据。您的发送缓冲区大小为 256。在通过缓冲区传输 256 个字符之前,您的数据不会发送到另一端。当您知道您准备好发送时,您可以通过在缓冲区上调用刷新方法来解决此问题。

需要明确的是,您正在内部缓冲,然后当您调用 send() 并传递一些数据时,操作系统(或库)再次缓冲。

如果您更具体地了解您正在使用的库,并且可能包含代码片段,我们可能会找到正确的缓冲区刷新函数来发送您使用。

或者,如果您在 *nix 中,只需关闭 Nagle 的算法,这样操作系统就不会缓冲您的小数据包。或者,当您设置套接字时,请确保使用 TCP_NODELAY 选项

于 2009-04-15T00:36:33.480 回答
0

Socket 编程繁琐、容易出错且不可移植。开始使用BoostACE之类的库,它们可以保护您免受低级 C API 的影响,并为您提供与平台无关的抽象。

于 2009-04-16T04:01:06.867 回答
0

Assuming this is a SOCK_STREAM socket, the important thing to be aware of is that the underlying TCP protocol does not maintain any segment boundaries. That is, when you call send() multiple times, all of the data you sent may very easily be returned by a single recv() call at the other end. Or, the data sent in one send() call may be returned in multiple recv()s at the other end, e.g. if some packets got delayed due to network congestion. This is fundamental to the design of TCP, and your application must be designed accordingly.

Also, as noted by Mehrdad, the recv() call returns the number of bytes that were read off the wire. Anything after that point in the buffer is garbage, and the data is not zero-terminated.

A SOCK_DGRAM socket uses UDP underneath, which is entirely packet-oriented, as opposed to stream-oriented like TCP. However, UDP does not guarantee reliability (the U stands for Unreliable), so you have to handle lost, duplicated, out-of-order etc. packets yourself. This is a lot harder than stream-oriented I/O.

于 2009-04-15T02:40:35.477 回答