【问题标题】:C++ socket 256 byte bufferC++ 套接字 256 字节缓冲区
【发布时间】:2009-04-15 00:34:48
【问题描述】:

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

“Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!”

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

谢谢

【问题讨论】:

  • 你是否终止了你的字符串? “Hello World!\0”

标签: c++ sockets buffer


【解决方案1】:

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

int count = read(...);
// buffer[0 .. count - 1] contains the appropriate data.

【讨论】:

  • 只是让你知道,接收数据的服务器是用 C# 制作的
  • QAH:对于 C# 套接字,Socket.Receive 方法也是如此。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案4】:

      假设这是一个 SOCK_STREAM 套接字,需要注意的重要一点是底层 TCP 协议不维护任何段边界。也就是说,当您多次调用 send() 时,您发送的所有数据可能很容易被另一端的单个 recv() 调用返回。或者,在一个 send() 调用中发送的数据可能会在另一端的多个 recv() 中返回,例如如果某些数据包由于网络拥塞而延迟。这是 TCP 设计的基础,您的应用程序必须相应地进行设计。

      此外,如 Mehrdad 所述,recv() 调用返回从线路读取的字节数。缓冲区中该点之后的任何内容都是垃圾,并且数据不是以零结尾的。

      SOCK_DGRAM 套接字在底层使用 UDP,它完全面向数据包,而不是像 TCP 那样面向流。但是,UDP 不保证可靠性(U 代表 Unreliable),因此您必须自己处理丢失、重复、乱序等数据包。这比面向流的 I/O 困难得多。

      【讨论】:

      • UDP 是用户数据报协议 - 它的名称与不可靠无关。不过,您说得对,它相对不可靠:)
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2012-12-15
        • 2016-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-25
        • 2021-11-02
        • 1970-01-01
        相关资源
        最近更新 更多