【问题标题】:Non-block socket consecutive file transfer非阻塞套接字连续文件传输
【发布时间】:2012-03-03 07:09:00
【问题描述】:

我正在处理的服务器(这是一个 Unix C 多线程非阻塞套接字服务器)需要从客户端接收文件并将其广播给连接到服务器的所有其他客户端。

一切都在我很难确定文件何时完成传输的例外情况下工作......因为我使用非阻塞套接字我遇到了有时在文件传输期间recv返回-1(我假设是文件的结尾)然后下一次传递更多字节。

我尝试破解将“END”放在流末尾的整个内容。但是,有时当连续发送多个文件时,“END”是与下一个文件开头相同的 recv 缓冲区的一部分。或者更糟糕的是,有时我最终会得到一个以 EN 结束的缓冲区,而下一次通过 D 进入。

避免上述情况的最佳方法是什么,我真的不希望每次我从套接字循环接收一些字节时整个累积的缓冲区都检查“END”是否是它的一部分然后适当地切割...我确定有更好的解决方案吗?

提前致谢!

【问题讨论】:

  • 为什么不先发送文件大小,然后再发送数据本身?

标签: c sockets tcp


【解决方案1】:

如果recv() 返回 -1,这是一个错误,您需要检查errno。很可能是EAGAINEWOULDBLOCK,这只是意味着当前套接字接收缓冲区中没有数据。所以需要re-select()。

recv() 返回时,对端已断开套接字并且传输完成。

【讨论】:

  • 重新选择是什么意思?我不想在等待状态时停止线程循环...我需要同时处理其他客户端的传输...
  • @McBob 我不明白。使用非阻塞 I/O 的全部原因是您可以在一个线程中处理多个客户端。这就是 select() 的用途。当recv() 返回-1 并且errnoEAGAIN/EWOULDBLOCK 时,您继续处理下一个就绪的FD。当您不在这些范围内时,请重新选择。
【解决方案2】:

用某个字节序列表示文件结束是不可靠的,文件可能包含该序列。首先发送文件长度 - 4 字节或 8 如果您允许大文件传输,请使用网络字节顺序。

if ((n = read(..., filelen)) > 0) {
    filelen -= n;
} 

【讨论】:

    【解决方案3】:

    EJP 所指的最简单的情况,即您将另一端关闭套接字作为文件结束的情况,可能如下所示:

    {
      ssize_t sizeRead = 0;
    
      while (sizeRead = recv(...)) {
        if (0 > sizeRead) { /* recv() failed */
          if ((EGAGAIN == errno) ¦¦ (EWOULDBLOCK == errno)) { /* retry the recv() on those two kinds of error */
            usleep(1) /* optional */
            continue;
          }
          else
            break;
        }
    
        ... /* process the data read ... */
      }
    
      if (0 > sizeRead) {
        /* There had been an error during recv() */
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-04-18
      • 2013-07-20
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 2010-10-31
      • 2013-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多