gpt4 book ai didi

perl - 如何将套接字保存在哈希中并从另一个线程循环它们?

转载 作者:行者123 更新时间:2023-12-03 21:13:18 24 4
gpt4 key购买 nike

我正在开发一个多线程 TCP 服务器。在主线程中,我监听一个套接字并为新的传入连接创建一个新线程。我想将所有传入连接保存在哈希中,以便我可以从另一个线程访问它们。

从监视器线程中,我无法读取任何新添加的连接。创建监视器线程时似乎创建了一个新的客户端哈希。

我如何保留所有套接字的列表并从我的监视器线程中循环它们?

当前代码:

#!/usr/bin/perl
use strict;
use IO::Socket;
use threads;
use Thread::Queue;

# init
my $clients = {};
my $queue = Thread::Queue->new;

# thread that monitors
threads->create("monitor");

# create the listen socket
my $listenSocket = IO::Socket::INET->new(LocalPort => 12345,
Listen => 10,
Proto => 'tcp',
Reuse => 1);

# make sure we are bound to the port
die "Cant't create a listening socket: $@" unless $listenSocket;

print "Server ready. Waiting for connections on 34567 ... \n";

# wait for connections at the accept call
while (my $connection = $listenSocket->accept) {
# set client socket to non blocking
my $nonblocking = 1;
ioctl($connection, 0x8004667e, \\$nonblocking);

# autoflush
$connection->autoflush(1);

# debug
print "Accepted new connection\n";

# add to list
$clients->{time()} = $connection;

# start new thread and listen on the socket
threads->create("readData", $connection);
}

sub readData {
# socket parameter
my ($client) = @_;

# read client
while (<$client>) {
# remove newline
chomp $_;

# add to queue
$queue->enqueue($_);
}

close $client;
}

sub monitor {
# endless loop
while (1) {

# loop while there is something in the queue
while ($queue->pending) {

# get data from a queue
my $data = $queue->dequeue;

# loop all sockets
while ( my ($key, $value) = each(%$clients) ) {

# send to socket
print $value "$data\n";

}
}

# wait 0,25 seconds
select(undef, undef, undef, 0.25);
}
}

close $listenSocket;

最佳答案

你需要分享$clients通过 share来自 threads::shared :

my $clients = &share({});

老式的语法是由于 Perl 原型(prototype)的一个记录问题。如果您有 at least Perl 5.8.9 , 使用更好的
my $clients = shared_clone({});

反而。

您还想保护 $clients带锁,例如,
my $clients_lock : shared;
{
lock $clients_lock;
$clients->{time()} = fileno $connection;
}

最后,因为 IO::Socket::INET实例是 Perl 类型团,您不能共享它们,因此请将它们的套接字描述符(来自 fileno )添加到 $clients然后 fdopen必要时与 socket
open my $fh, ">&=", $sockdesc or warn ...

下面的程序将入站数据重复到其他连接的套接字:
#!/usr/bin/perl

use strict;
use IO::Socket;
use threads;
use threads::shared;
use Thread::Queue;

# init
my $clients = &share({});
my $clients_lock : shared;

my $queue = Thread::Queue->new;

# thread that monitors
threads->create("monitor");

# create the listen socket
my $port = 12345;
my $listenSocket = IO::Socket::INET->new(
LocalPort => $port,
Listen => 10,
Proto => 'tcp',
Reuse => 1
);

# make sure we are bound to the port
die "Can't create a listening socket: $@" unless $listenSocket;

print "Server ready. Waiting for connections on $port ... \n";

# wait for connections at the accept call
while (my $connection = $listenSocket->accept) {
# set client socket to non blocking
my $nonblocking = 1;
ioctl($connection, 0x8004667e, \\$nonblocking);

# autoflush
$connection->autoflush(1);

# debug
print "Accepted new connection\n";

# add to list
{
lock $clients_lock;
$clients->{time()} = fileno $connection;
}

# start new thread and listen on the socket
threads->create("readData", $connection);
}

sub readData {
# socket parameter
my ($client) = @_;

# read client
while (<$client>) {
chomp;
$queue->enqueue($_);
}

close $client;
}

sub monitor {
# endless loop
while (1) {
# loop while there is something in the queue
while ($queue->pending) {
# get data from a queue
my $data = $queue->dequeue;

# loop all sockets
{
lock $clients_lock;
while ( my ($key, $value) = each(%$clients) ) {
# send to socket
if (open my $fh, ">&=", $value) {
print $fh "$data\n";
}
else {
warn "$0: fdopen $value: $!";
}
}
}
}

# wait 0,25 seconds
select(undef, undef, undef, 0.25);
}
}

close $listenSocket;

关于perl - 如何将套接字保存在哈希中并从另一个线程循环它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2202892/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com