recv延迟()

时间:2011-10-28 22:15:55

标签: c sockets send recv ioctl

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

是因为p2中的send()和p2中的recv()有延迟,p2只识别套接字中的16385个字符?

对于前: 如果P1发送长度(16388)

P2只接收以下长度(16385)

2 个答案:

答案 0 :(得分:5)

说我试图送你8个南瓜。我把6个放在桌子上。你想,“我期待8个南瓜,而不是6个。我会等到他把最后两个放在桌子上。”我想,“我不想在飞行中同时使用太多的南瓜。我会等到这6个中的2个然后把最后的2个放在桌子上。”我们被困住了。我们每个人都在等待对方。我们会永远等待。

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

因此接受收到的字节。在接受任何一方之前,不要等待对方发送所有这些。否则,如果对方在发送之前等待你接受第一个会发生什么呢?

答案 1 :(得分: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.