recv() 接收部分消息的套接字编程问题

Posted

技术标签:

【中文标题】recv() 接收部分消息的套接字编程问题【英文标题】:Socket programming issue with recv() receiving partial messages 【发布时间】:2012-04-20 17:18:01 【问题描述】:

我有一个正在接收流式股票报价数据的套接字。但是,我似乎收到了很多被截断的消息,或者似乎是被截断的消息。以下是我接收数据的方式:

if((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) 
    perror("recv()");
    exit(1);

else 
    buf[numbytes] = '\0';
    // Process data

recv() 能否仅接收已发送内容的部分消息?

我的感觉是我可能需要围绕 recv() 调用的另一个循环,直到发送完整的消息。我知道我拥有的 libcurl 实现(我认为这里不可能使用 libcurl)有一个外循环:

// Read the response (sum total bytes read in tot_bytes)
for(tot_bytes=0; ; tot_bytes += iolen)
  
    wait_on_socket(sockfd, 1, 60000L);
    res = curl_easy_recv(curl, buf + tot_bytes, sizeof_buf - tot_bytes, &iolen);

    if(CURLE_OK != res) 
        // printf( "## %d", res );
        break;
    

我是否需要一个类似于 libcurl 示例的 recv() 循环(可验证有效)?

【问题讨论】:

不完全相关,但为什么要通过 TCP 发送刻度数据?这些东西通常是通过 UDP 多播的。 我正在接收,而不是发送。他们只是通过电子邮件向我发送了主机名和端口号,我没有收到任何其他技术说明。我刚刚发送了一封电子邮件,询问我是否应该使用 UDP。但是如果我使用 TCP 并且它可以工作(除了我打开主题的部分消息问题)它是否也可以与 UDP 一起工作?即 - 他们发送 UDP,我可以使用 UDP 或 TCP 来接收()?此外,他们确实发送 标头,所以我认为我需要使用它们来检测部分消息,然后当我下一次 recv() 时,偏移到部分消息中以尝试和完成它..谢谢。 我没有得到的 UDP 评论 - 如果您使用 UDP,您可能会丢失数据,对吧? 是的,UDP 可能会丢失数据。这就是为什么它被用于蜱虫;如果您错过了报价更新,交易所不会等待并重新发送。交换只是多播给每个人,希望你能得到大部分。我很困惑为什么你的市场数据系统会有不同的设置。通常主机和端口是指您拥有 join 的多播 group 【参考方案1】:

我们也可以将标志传递给recv 以等待所有消息到达。当您知道要接收的字节数时,它就会起作用。你可以像这样传递命令。

numbytes =  recv(sockfd, buf, MAXDATASIZE-1, MSG_WAITALL);

【讨论】:

【参考方案2】:

你是对的,你需要一个循环。 recv 只检索当前可用的数据;一旦读取了任何数据,它不会等待更多数据出现才返回。

manual page 说 “接收调用通常会返回任何可用的数据,直到请求的数量,而不是等待收到请求的全部数量。”

【讨论】:

【参考方案3】:

TCP 不尊重消息边界。这意味着 recv() 不能保证完全按照您的假设获得整个消息。这就是为什么您需要围绕recv() 进行循环的原因。 (这也是为什么像 HTTP 这样的上层协议要么关闭套接字,要么在前面添加一个长度指示符,以便接收者准确地知道何时停止从套接字读取。)

【讨论】:

【参考方案4】:

recv() 能否只接收已发送内容的部分消息?

是的,确实,如果您使用 TCP。我认为这可以帮助你。 Handling partial return from recv() TCP in C

【讨论】:

感谢链接。从阅读中,实际上我收到的味精有标题。例如 2, , 。我的 recv 通常返回 100,最后一个被截断。所以,我可能应该“处理我得到的东西”并将下一个 recv() 设置为使用偏移量,以便完成最后一个部分 msg。不要以为我能一一拿到这些,数据太多了。这是 BATS 的 RT 提要。

以上是关于recv() 接收部分消息的套接字编程问题的主要内容,如果未能解决你的问题,请参考以下文章

ioctlsocket 或 recv 在 Windows 套接字编程中需要更多时间来执行?

C++ 套接字 recv() 系统调用返回 -1

ioctl() 用于 C 中的套接字编程

Python套接字recv()由于硬件而挂起?

ZeroMQ 套接字 Recv() 抛出“上下文已终止”异常 - 为啥以及如何恢复?

C 套接字可以在没有客户端关闭连接的情况下接收 0 个字节吗?