如何处理Perl TCP套接字中的消息碎片?

Igo*_*Oks 2 c++ sockets perl tcp communication

我在Perl客户端和C++服务器之间有套接字通信.

Perl代码:

  if (!socket(SERVER, AF_INET, SOCK_STREAM, getprotobyname('tcp'))) {
    die "Can't allocate socket\n";
  } elsif (!connect(SERVER,sockaddr_in($PORT, $tcp_addr))) {
    die "Can't connect to server at $tcp_addr port $PORT...\n";
  }

  SERVER -> autoflush(1);

  print SERVER "$line";
Run Code Online (Sandbox Code Playgroud)

如果$line太长了,它就会碎片化,而在C++服务器端我必须recv多次调用(甚至不知道实际的预期长度!).

处理它的最佳方法是什么?

我想到了一些方法:

  1. 也许有一些Perl模块可以处理它?
  2. 也许我可以关闭碎片,但不会导致更多的传输失败?
  3. 我可以将消息长度添加到已发送的消息中,我会打电话recv直到收到整条消息,但这不是很难看吗?
  4. 还要别的吗?

最好的解决方案是什么?

Pla*_*aHH 5

将消息长度添加为消息的4字节标头.这并不难看,但正如"专业人士"所做的那样.TCP/IP是面向流的协议.你很幸运,你在一次电话会议中得到了你的消息.有可能获得任意数量的字节,只有一半的消息,一个半的消息等,因为tcp/ip正在传输连续的字节流,而没有该级别的任何数据包概念.

好的一面是你可以在用户空间中缓冲你的消息,并且可以将所需的字节读取到该缓冲区中,并且该缓冲区中的多个消息的进程不再重复调用recv()

  • @blankabout:你似乎对单个TCP数据包的IP碎片感到困惑,因为当你通过tcp发送()输出一些字节时,操作系统可以自由地将它放入它认为有用的尽可能多的TCP消息中.因此,根据它如何分割数据以及recv()调用的时间,缓冲区将仅填充部分消息,完整消息或多个消息.除非发件人使用软木塞,否则当它以足够快的速度发送()多条消息时,你几乎不会有recv()正好一条消息的情况. (2认同)

Dav*_*rtz 5

最好的解决方案是继续调用“recv”,直到收到完整的消息。如果需要确定何时拥有完整消息,请在消息前面加上消息长度或在消息后面添加终止符。我不知道你为什么认为那很丑。