我正在创建一个与Teamspeak接口的程序,我遇到的问题是收到的响应与发送的命令不匹配。我多次运行该程序,每次都会得到不同的结果,因为响应不同步。
my $buf = '';
use IO::Socket;
my $sock = new IO::Socket::INET (
PeerAddr => 'localhost'
,PeerPort => '10011'
,Proto => 'tcp'
,Autoflush => 1
,Blocking => 1
,Timeout => 10
);
sub ExecuteCommand{
print $sock $_[0]."\n";$sock->sysread($buf,1024*10);
return $buf;
};
ExecuteCommand("login ${username} ${password}");
ExecuteCommand("use sid=1");
ExecuteCommand("clientupdate client_nickname=Idle\\sTimer");
my $client_list = ExecuteCommand("clientlist");
每个命令都正确执行,但服务器喜欢返回额外的行,因此单个sysread将不够,我将不得不执行另一个。响应的大小最多为512,因此它们不会被切断。如果我尝试多次运行sysread以尝试刷新它,当没有任何内容可读时它只会让程序挂起。
执行结束之后是“error id = 0 msg = ok”
我怎样才能读出所有出来的数据,即使它是多行?或者只是能够将它全部冲洗掉,这样我就可以移动到下一个命令而不必担心旧数据?
答案 0 :(得分:0)
所以你要阅读,直到找到以error
开头的行。除此之外,以下缓冲任何额外的读取,因为它是下一个响应的一部分。
sub read_response {
my ($conn) = @_;
my $fh = $conn->{fh};
our $buf; local *buf = \($conn->{buf}); # alias
our $eof; local *eof = \($conn->{eof}); # alias
$buf = '' if !defined($buf);
return undef if $eof;
while (1) {
if ($buf =~ s/\A(.*?^error[^\n]*\n)//ms) {
return $1;
}
my $rv = sysread($fh, $buf, 64*1024, length($buf));
if (!$rv) {
if (defined($rv)) {
$eof = 1;
return undef;
} else {
die "Can't read response: $!\n";
}
}
}
}
my $conn = { fh => $sock };
... send command ...
my $response = read_response($conn);
...
... send command ...
my $response = read_response($conn);
...
答案 1 :(得分:0)
我更改了我的ExecuteCommand
子例程以包含对“错误代码= [0-9] {1,}”的检查,这是Teamspeak 3服务器响应结束时的总是。
sub ExecuteCommand{
print $sock $_[0]."\n";
my $response = "";
while (1){
$sock->sysread($buf,1024*10);
last if($buf =~ /error id=([0-9]{1,})/);
$response .= $buf;
};
return $response;
};