我有一个TCP Socket beetwen两个程序,一个C#服务器和一个Perl客户端.客户端应该从服务器接收XML流. XML文件(由C#程序生成)大约为437KB,但是无论缓冲区有多大,客户端都只会收到408KB.在客户端,我使用IO :: Socket :: INET,而服务器端使用TcpListener和TcpClient的组合.如何在客户端正确定义缓冲区?现在我正在使用该代码:
# 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();
解决方法:
我从不使用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确定问题是出在发送方,接收方还是两者之间.
sysread和read的“怪癖”:
sysread总是在字节字节可用时立即返回,无论请求了多少字节.这意味着如果调用时字节已经可用,它将立即返回.它将阻塞直到有其他数据包进入.这意味着如果需要特定数量的字符,则需要循环.
相反,读取将等待直到请求的字节数可用为止.然后仅在EOF或错误时返回.
read和sysread实际上在字符级别上工作,这意味着您实际上指定了所需的字符数,而不是字节数.这些字符可以是字节,Unicode代码点或其他内容,具体取决于您添加到句柄的IO层.