0

我有两个使用套接字编程进行通信的程序。最初,我将指定编号。关于他们必须在彼此之间交换消息的时间的跳数。每次它收到一条消息时,它都会将它的 id 附加到它上面。因此,字符串每次都会变大。我的程序在 8000 跳时运行良好,但是在超过 8000 跳之后,虽然程序 p1 发送了一个长度为 16388 的字符串,但 p2 确定套接字中只有 16385 可以读取。我使用 ioctl() 来确定套接字中准备接受 recv() 的字符数量,然后在 char * 变量中接收它...

是否因为 p1 中的 send() 和 p2 中的 recv() 存在延迟,所以 p2 仅识别套接字中的 16385 个字符?

例如:如果 P1 发送长度(16388)

P2 仅接收以下长度(16385)

4

2 回答 2

6

假设我想寄给你 8 个南瓜。我把其中的6个放在桌子上。你想,“我期待 8 个南瓜,而不是 6 个。我会等到他把最后两个放在桌子上。” 我想,“我不希望一次有太多的南瓜‘飞行’。我会等到他拿走这 6 个中的 2 个,然后再把最后 2 个放在桌子上。” 我们被困住了。我们每个人都在等待对方。我们将永远等待。

在接受已经收到的字节之前,不允许您等到收到更多字节。原因很简单:没有网络协议可以让双方都等待对方。由于 TCP 允许发送方在此上下文中等待,它不能允许接收方也等待。

所以接受接收到的字节。不要等对方全部发完才接受。否则,如果对方正在等待你接受第一个,然后再发送,会发生什么?

于 2011-10-28T22:26:59.047 回答
0

您可能正在达到内核缓冲区限制。您可能可以在接收器上增加 SO_RCVBUF 并且它会按预期工作:SIOCINQ 最终将返回未读数据的完整大小。

但是您不应该这样做以确保正常运行。只有在您想调整性能时才应该弄乱缓冲区。

您应该重构代码,这样您就不必询问内核有多少字节可用。只需阅读到一个合理的限制(如 4096)并处理一个应用程序级消息被分解为多个部分。如果您需要消息长度/边界,那么您必须自己在 TCP 之上实现它们。

这是一些愚蠢的代码来读取带有长度标头的消息:

int ret, len = 0, have_read;
have_read = 0;
while (have_read < sizeof(len)) {
    // This will likely always return sizeof(len) the first time.
    ret = read(fd, ((char*)&len) + have_read, sizeof(len) - have_read);
    if (ret <= 0) {
        // Handle error.
    }
    have_read += ret;
}
char* buf = malloc(len);
if (!buf) {
    // Handle error.
}
have_read = 0;
while (have_read < len) {
    ret = read(fd, buf + have_read, len - have_read);
    if (ret <= 0) {
        // Handle error.
    }
    have_read += ret;
}
// Handle message in buf.
于 2011-10-28T23:09:05.120 回答