【问题标题】:socket read get all data before return套接字读取在返回之前获取所有数据
【发布时间】:2014-05-20 12:39:47
【问题描述】:

我正在编写一个 tcp 代理,它维护一个消息队列。一旦得到服务器的响应,我需要从队列中弹出前面的消息。问题是我的服务器响应消息的大小很大,读取函数将在所有数据收集之前返回。我该如何处理这个问题?

【问题讨论】:

  • 几个想法是 1) 在数据本身之前传递数据的大小并读取直到读取了那么多字节,或者 2) 在末尾有一些标记消息结束的东西它。
  • 为什么要排队?代理服务器没有队列。在大多数情况下,它们只是读取和写入字节。
  • 这个问题有必要处理吗?如果您只发送()接收到的字节,会出现什么问题?
  • @itsme86 消息长度不固定且未知,我认为最好循环直到不再像其他人所说的那样有消息出现
  • @EJP 是的,我不能,因为我的每条消息都是一个实体,而且我有多个客户端,这就是为什么我需要一个消息队列:P

标签: c sockets message-queue


【解决方案1】:

没有看到任何代码 sn-ps 来了解所涉及的数据结构,听起来您只需要循环您的套接字 read() 调用,直到您读取足够的数据以满足“完整消息”的约束。收到完整消息后,您可以将其放入队列并弹出第一个消息,或者如果是第一个则直接返回。

【讨论】:

    【解决方案2】:

    粗略地说,你需要一个这样的循环:

    size_t read_buffer(int sockfd, char *buffer, size_t reqlen)
    {
        char   *cur_buffer = buffer;
        size_t  bytes_left = reqlen;
        ssize_t bytes_read;
        while ((bytes_read = read(sockfd, cur_buffer, bytes_left)) > 0)
        {
            cur_buffer += bytes_read;
            bytes_left -= bytes_read;
        }
        return(cur_buffer - buffer);
    }
    

    您可以决定如何处理读取错误 — 是返回读取的字节数还是返回错误指示(可能是 -1)。代码返回读取的字节数;如果它不是请求的长度,则可以合理地假设丢失的字节永远不会出现(因此您可能最终会忽略调用代码中读取的内容)。您可能想识别bytes_read == -1 && errno == EINTR(读取被中断)并再次尝试读取。

    警告:未编译,测试更少,代码!

    【讨论】:

      【解决方案3】:

      我不知道你为什么认为你需要对消息进行排队、组合完整的响应等,而且你还没有回答发布的 cmets 询问这个问题,但是一旦初始握手完成,所有的都是正常的代理服务器要做的是在两个方向同时复制字节,当它们到达时,根本不关心消息:

      while ((count = recv(insocket, buffer, 0, sizeof buffer, 0)) > 0)
      {
          send(outsocket, buffer, 0, count, 0);
      }
      

      您需要两个线程,一个在每个方向上执行此操作,每个连接。当两个线程都退出这些循环时,关闭两个套接字。

      【讨论】:

        猜你喜欢
        • 2014-09-15
        • 2013-07-10
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 2020-02-10
        • 2013-02-13
        • 2011-06-16
        • 2016-02-17
        相关资源
        最近更新 更多