C++套接字256字节缓冲区

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

现在有趣的部分来了。“Hello World!”这句话立即发送,如果我将缓冲区大小设置为256 (char buffer[256];)。然而,当以这种方式发送到服务器时,它显示出“Hello World!”后面的一堆空格。为什么会这样,并且如果可能,如何解决?请告诉我。

谢谢。


你是否在字符串末尾添加了空字符?"Hello World!\0" - Alan
5个回答

7
当您使用缓冲区调用read(或receive)从套接字读取时,将返回一个整数值,指定读取的字节数。 您应该只从缓冲区中取出这么多内容。 其余部分是不相关的。
int count = read(...);
// buffer[0 .. count - 1] contains the appropriate data.

只是想让您知道,接收数据的服务器是用C#制作的。 - QAH
QAH:对于C#套接字,Socket.Receive方法也是如此。 - Mehrdad Afshari

6
通常情况下,Nagle算法默认开启。该算法能够将多个小数据包合并成一个大的数据包进行传输。关闭Nagle算法将允许立即发送小型数据包。

4
缓冲区存在的目的是为了存储数据,直到您准备好发送它。您的发送缓冲区大小为256。在256个字符通过缓冲区传输之前,您的数据不会被发送到另一端。当您准备好发送时,可以通过调用缓冲区上的flush方法来解决此问题。
需要明确的是,您正在进行内部缓冲,然后在调用send()并传递一些数据时,操作系统(或库)再次进行缓冲。
如果您可以更具体地说明您使用的库,并可能包括代码片段,我们可能会找到正确的缓冲区刷新函数,以便您顺利完成。
或者,如果您在*nix中,只需关闭Nagle算法,以便操作系统不会缓冲您的小数据包。或者,在设置套接字时,请确保使用TCP_NODELAY选项。

0
假设这是一个SOCK_STREAM套接字,需要注意的重要事情是底层TCP协议不维护任何段边界。也就是说,当您多次调用send()时,您发送的所有数据很容易由另一端的单个recv()调用返回。或者,发送在一个send()调用中的数据可能会在另一端的多个recv()中返回,例如,如果由于网络拥塞而延迟了一些数据包。这是TCP设计的基础,您的应用程序必须相应地设计。
此外,正如Mehrdad所指出的那样,recv()调用返回从线路读取的字节数。缓冲区中该点之后的任何内容都是垃圾,并且数据没有零终止符。
SOCK_DGRAM套接字使用UDP作为底层协议,它完全是面向数据包的,而不像TCP那样是面向流的。但是,UDP不能保证可靠性(U代表Unreliable),因此您必须自己处理丢失、重复、乱序等数据包。这比面向流的I/O要困难得多。

UDP是用户数据报协议 - 其名称中并没有提到不可靠。但您说得对,它相对而言确实不太可靠 :) - Steven Schlansker

0

Socket编程是繁琐、容易出错且不可移植的。开始使用像BoostACE这样的库,它们可以为您屏蔽底层C API,并为您提供平台无关的抽象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接