C# / Perl连接中的套接字缓冲区溢出问题

3
我有一个TCP套接字,连接着一个C#服务器和一个Perl客户端。客户端应该从服务器接收XML流。XML文件(由C#程序生成)大约有437KB,但是客户端只能接收到408KB,无论缓冲区大小如何。在客户端上,我使用IO::Socket::INET,而服务器端使用了TcpListenerTcpClient的组合。我该如何正确定义客户端缓冲区?现在我正在使用以下代码:
# PERL CLIENT
my $socket = new IO::Socket::INET (
    PeerHost => '192.168.*.*',
    PeerPort => '*****',
    Proto => 'tcp'
) or die "Error while creating Socket";
#
# OTHER STUFFS...
#
my $buffer = 500000000; # IT DOESNT SEEM TO USE THAT VALUE AT ALL
$socket->recv($xmlbody, $buffer);


// C# SERVER
// OTHER STUFFS...
byte[] result = encoding.GetBytes(xml);
clientStream.Write(result, 0, result.Length);
clientStream.Flush();
clientStream.Close();
tcpClient.Close();

听起来像是发送方被缓存了,你需要刷新缓存。你可以使用 tcpdump 或类似工具验证这是否是发送方的问题。 - ikegami
1
你在发送XML后是否关闭了流?或者你是在XML前加上了它的长度?我的意思是,你如何知道读取器应该读取多少字节? - ikegami
是的,服务器在发送XML后正在刷新并关闭流。事实是我不知道读取器应该读取多少字节,这相当随机,而且在XML文件变得如此庞大时,我从来没有遇到过这个问题。您是否建议首先将文件长度发送给接收者? - raz3r
1
关闭发送方足以表示何时停止读取。如果您没有这样做,我建议发送长度。既然您已经这样做了,就不需要发送长度了。 - ikegami
1个回答

4

我从不使用recv,所以我不了解它的怪癖。我使用sysread

sub read_until_eof {
   my ($fh) = @_;
   my $buf = '';
   for (;;) {
      my $rv = sysread($fh, $buf, 64*1024, length($buf))
      die $! if !defined($rv);
      return $buf if !$rv;
   }
}

如果这样做不起作用,我建议您使用tcpdump来确定问题是在发送方、接收方还是中间某个位置。
sysreadread的“怪癖”: sysread总是返回字节可用的数量,而不管请求了多少字节。这意味着如果调用时已经有可用字节,它会立即返回。否则,它将一直阻塞,直到收到数据包。这意味着如果想要特定数量的字符,就需要循环读取。
相比之下,read会等待所请求的字节数可用。只有当达到EOF或出现错误时,它才会返回。 readsysread实际上是在字符级别上工作的,这意味着您实际上指定了所需的字符数,而不是字节数。这些字符可以是字节、Unicode代码点或其他内容,具体取决于您添加到句柄的IO层。

我从未使用过sysread,总是用recv,但是嘿,那也很好用!谢谢大家的帮助! - raz3r
@raz3r,我应该提到sysread的“怪癖”。现在添加它们。 - ikegami

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接