【发布时间】:2010-09-10 00:02:49
【问题描述】:
我正在尝试编写通过 Unix 套接字进行双向通信的 Perl 代码。它需要做以下事情:
- 客户端代码通过套接字发送请求
- 服务器代码读取请求
- 服务器执行任何应该立即发生的操作
- 服务器创建一个新线程来执行可能需要很长时间的其他操作
- 服务器通过套接字发送响应
- 客户端收到响应
- 发送响应后新线程继续工作
我现在已经完成了大部分工作,但有一个问题。第 1 - 5 步工作正常,但在第 6 步,客户端无法读取响应,直到线程退出后。 (即使响应或多或少立即发送)知道我做错了什么吗?
我在 Ubuntu Lucid 上使用 Perl 5.10.1。
这是一个例子:
客户端代码:
#!/usr/bin/perl
use strict;
use Socket;
my $socket_name = 'catsock';
my $client_message = "Hello server, this is the client.";
my $SOCK;
socket($SOCK, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
connect($SOCK, sockaddr_un($socket_name)) or die "connect: $!";
$| = 1, select $_ for select $SOCK; # turn on autoflush
print $SOCK $client_message; # send the message
shutdown($SOCK,1); # finished writing
print "sent: $client_message\n";
my $server_message = do { local $/; <$SOCK> }; # get the response
print "recieved: $server_message\n\n";
服务器代码
#!/usr/bin/perl
use strict;
use Socket;
use threads;
use threads::shared;
sub threadfunc
{
print " waiting 5 seconds in new thread...\n";
sleep(5);
print " exiting thread...\n\n";
}
my $server_message = "Hello client, this is the server.";
my $socket_name = 'catsock';
my $SERVER;
my $CLIENT;
socket($SERVER, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
unlink($socket_name);
bind($SERVER, sockaddr_un($socket_name)) or die "bind: $!";
chmod(0660, $socket_name);
listen($SERVER, SOMAXCONN) or die "listen: $!";
print "server started on $socket_name\n\n";
while(1) {
accept($CLIENT, $SERVER);
my $client_message = do { local $/; <$CLIENT> }; # grab entire message
print "recieved: $client_message\n";
print "creating new thread...\n";
my $thr = threads->create(\&threadfunc);
$thr->detach();
print $CLIENT $server_message; # send the response
print "sent: $server_message\n\n";
close $CLIENT;
}
当我运行它时,会发生以下事情:
- 客户端发送“你好服务器,这是客户端。”
- 服务器收到客户端的消息
- 服务器创建一个新线程
- 服务器发送“你好客户端,这是服务器。”
- 客户端现在应该会收到消息,但没有收到。
- 服务器上的新线程休眠 5 秒
- 线程退出
- 现在客户端收到服务器的消息,即使它是在 5 秒前发送的。为什么?
【问题讨论】:
-
设置
$CLIENT在接受后自动刷新? -
是否有可能是服务器线程在 $thread->detach 方法中阻塞,因此 $CLIENT 上的写入在工作线程退出之前不会执行?
-
@feroze - 额外的线程使连接保持打开 5 秒(尽管我不确定具体如何 - 线程有一个
$CLIENT的私有副本,并且连接不会关闭,直到所有副本都超出范围,也许),但它不会延迟写入$CLIENT。 -
打印 $CLIENT "$server_message\n" ? #疯狂猜测
标签: multithreading perl sockets