zhanying请进,请教cmpp2.0程序的问题

zhanying请进,请教cmpp2.0程序的问题

zhanying请进,请教cmpp2.0程序的问题
我对下面这段代码存有疑问,
while ($handle->can_read()) {
my [color=red]$Socket_Size [/color] = (stat($socket))[7];
if ($Socket_Size == 0) { return (-1) }
sysread($socket, my $come_packet, $Socket_Size);
($in_length, $in_command, $sequence, $in_content) =
unpack("N H8 a4 a*", $come_packet)
or die "cant $!";
return (0, $in_length, $in_command, $sequence, $in_content);
}
是否存在这样一种情况:$Socket_Size小于$in_length,一旦发生这种情况,那以后的解码不是都乱了吗?还请解释一下为何如此处理socket,而不是按照消息头中$in_length来处理。
这个好象是我写的程序,我.
这个好象是我写的程序,我就来解释一下

我为了用sysread从socket中读出数据,我必须事先知道每个包的大小。
因此我用 (stat($socket))[7]从socket中取出一个socket的大小$Socket_Size。
然后用sysread从socket中读出一个$Socket_Size大小的数据,也就是一个包。
然后用unpack进行分解,得到$in_length, $in_command, $sequence, $in_content这些数据。
$in_length实际上xmpp协议中的一个数据,用来表明自己包的大小的,和$Socket_Size无关,好像也没什么用处。
不好意思,搞错了,还有问题
那你又如何能保证每条短消息一定在一个socket包内,而不会被拆分到两个或更多包中呢?
这个确实不好保证,如果服.
这个确实不好保证,如果服务器端故意将原来的一个cmpp包分两次写入socket,那么我这边就错了,到时应该再加个检测$in_length与$socket_size的比对。

但是一般情况下,写socket程序会将一个包构建好后直接发到socket中,这样的话,只能是一个socket包包含一个或多个短消息,而不会一个短消息在几个包中了。
实际情况也是如此,好像有些投机取巧了:)
首先最大包长是固定的(以.
首先最大包长是固定的(以前算过,但不计得了),基本上一次读入4096应该可以保证一个包!有的时候还能一次读入两个包!所以我通常每次读入4096!

对于不能读入完整包的情况根据协议属于通信出错,应断开并重新建立连接!

对于一次读入多个包的情况可以根据包头中长度字段进行分割,如果发现末尾的包的长度根起包头中的长度不符,则说明缓冲区里面还有数据没有读出,应该再读一次!
不过最后这种情况的概率非常低,按照错误处理也是允许的!
至于故意分段写入我认为不.
至于故意分段写入我认为不必担心,因为通常不会有人故意将两次写入的间隔拉的很长,所以通常我们用一个read操作也是可以将分为两次写入的数据包读进来的。
[quote]回复给 zhanying :.
[quote]回复给 zhanying : 至于故意分段写入我认为不....[/quote]

呵呵,其实还要看服务器端的发送策略,如果服务器端不等待包累计到一定程度才发送,那么再小的包它也会立即发送,这样客户端就会出错了。

谢谢二位的精彩回答,很有收益
[CCB]1[/CCB][CCB]1[/CCB]
[quote]回复给 alexe : [q.
[quote]回复给 alexe : [quote]回复给 zhanying :....[/quote]
我觉得这个问题不大,我用Delphi的旧程序根Perl通讯过,利用Win2000的网络监视器察看Delphi分两次发送的包(消息头和消息体)Perl程序用一个Read也能读入(Delphi中也是这样)。
我想之所以会出现这种情况可能是Windows系统中Tcp/IP通讯的接收端的协议层应该有缓存区,所以临近的两个甚至更多个包都可以用一个Read来完成接收。
:),没错,只要你read时这两个包都在缓冲区了,你可以一次读入。

还有要注意的是在不同的平台下,socket的具体操作可能会有小的差异,还要看看系统的文档。