C++ 套接字 256 字节缓冲区
我正在尝试在 C++ 中使用一些套接字网络编程。 我正在尝试发送文本“Hello World!” 使用 C++ send() 函数发送到服务器。 首先,我将缓冲区的大小设置为 13,因为“Hello World!” 总共是 12 个字符(必须比字符数多 1 个)。 如果我发送大约 7 次,发送函数只会将字符发送到服务器。 当它最终到达服务器时,它看起来像这样:
“Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!”
现在这是有趣的部分。 “你好世界!” 如果我将缓冲区大小设置为 256 (char buffer[256];),句子会立即发送。 但当涉及到这样的服务器时,它会显示“Hello World!” 这两个词后面有一大堆空格。 为什么会发生这种情况?如果可能的话,我该如何解决它? 请告诉我。
谢谢
I am trying to use some socket network programming in C++. I am trying to send the text "Hello World!" to a server using the C++ send() function. At first, I set the buffer to the size of 13 since "Hello World!" altogether is 12 characters (you have to make it one more than the character count). The send function only sends the characters to the server if I send it about 7 times. And when it does finally come to the server it looks like this:
"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!"
Now here is the funny part. The "Hello World!" sentence sends immediately if I set the buffer size to 256 (char buffer[256];). When it comes to the server like that though, it shows "Hello World!" with a whole bunch of space after the two words. Why is this happening and if possible, how can I fix it? Please let me know.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当您使用缓冲区调用
read
(或receive
)以从套接字读取数据时,会返回一个整数值,该值指定读取的字节数。 您应该只从缓冲区中取出那么多。 其余的无关紧要:When you call
read
(orreceive
) with your buffer to read from the socket, an integer value is returned that specifies the number of bytes read. You should only take that much from the buffer. The rest is irrelevant:Nagle 算法通常默认开启。 这会将几个小数据包合并为一个。 关闭 Nagle 算法将允许立即发送小数据包。
Nagle's algorithm usually is turned on by default. This will combine several small packets into one. Turning Nagle's algorithm off will allow small packets to be sent immediately.
缓冲区的存在是为了存储数据,直到您准备好发送数据为止。 您的发送缓冲区大小为 256。在通过缓冲区传输 256 个字符之前,您的数据不会发送到另一端。 当您知道准备发送时,可以通过在缓冲区上调用刷新方法来解决此问题。
需要明确的是,您正在内部缓冲,然后当您调用 send() 并传递一些数据时,操作系统(或库)再次缓冲。
如果您更具体地了解您正在使用的库,并且可能包含代码片段,我们可能会找到正确的缓冲区刷新函数来发送给您。
或者,如果您在 *nix 中,只需关闭 Nagle 算法,这样操作系统就不会缓冲您的小数据包。 或者,当您设置套接字时,请确保使用 TCP_NODELAY 选项
Buffers exist to store data until you are ready to send it. You have a send buffer size of 256. Until 256 characters are transmitted through the buffer, your data won't be sent to the other side. You can fix this by calling a flush method on your buffer when you know you are ready to send.
To be clear, you are buffering internally, then the OS (or library) is buffering again when you call send() and pass some data.
If you get more specific with what library you are using and maybe include a code snippet, we can probably find the right buffer flush function to send you on your way with.
Alternatively, if you are in *nix, just turn off Nagle's algorithm so that the OS won't buffer your small packets. Or, when you set up you socket, make sure to use the TCP_NODELAY option
假设这是一个 SOCK_STREAM 套接字,需要注意的重要一点是底层 TCP 协议不维护任何段边界。 也就是说,当您多次调用 send() 时,发送的所有数据可能很容易由另一端的单个 receive() 调用返回。 或者,在一个 send() 调用中发送的数据可能会在另一端的多个 receive() 中返回,例如,如果某些数据包由于网络拥塞而延迟。 这是 TCP 设计的基础,您的应用程序必须进行相应的设计。
此外,正如 Mehrdad 所指出的,recv() 调用返回从线路读取的字节数。 缓冲区中该点之后的任何内容都是垃圾,并且数据不是以零结尾的。
SOCK_DGRAM 套接字在底层使用 UDP,它完全面向数据包,而不是像 TCP 那样面向流。 然而,UDP 不保证可靠性(U 代表不可靠),因此您必须自己处理丢失、重复、乱序等数据包。 这比面向流的 I/O 困难得多。
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.
套接字编程是乏味的、容易出错且不可移植的。 开始使用 Boost 或 ACE 使您免受低级 C API 的影响,并为您提供独立于平台的抽象。
Socket programming is tedious, error prone and non portable. Start using libraries like Boost or ACE that shield you from the low level C APIs and provide you with platform independent abstractions.