加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 如何在散列中保存套接字并从另一个线程循环它们?

发布时间:2020-12-15 21:49:53 所属栏目:大数据 来源:网络整理
导读:我正在使用多线程TCP服务器.在主线程中,我在套接字上侦听并为新的传入连接创建一个新线程.我想将所有传入连接保存在哈希中,以便我可以从另一个线程访问它们. 从监视器线程,我无法读取任何新添加的连接.在创建监视器线程时,似乎会创建一个新的客户端哈希. 如
我正在使用多线程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 connectionn";

    # 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 "$datan";

            }
        }

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

close $listenSocket;

解决方法

您需要通过 threads::shared分享$client:
my $clients = &share({});

旧式语法是由Perl原型的文档问题引起的.如果您有at least Perl 5.8.9,请使用更好的

my $clients = shared_clone({});

代替.

您还希望使用锁来保护$client,例如

my $clients_lock : shared;
{
  lock $clients_lock;
  $clients->{time()} = fileno $connection;
}

最后,因为IO :: Socket :: INET实例是Perl typeglobs,你不能共享它们,所以改为将它们的套接字描述符(从fileno)添加到$clients,然后在必要时用fdopen套接字

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,$nonblocking);

  # autoflush
  $connection->autoflush(1);

  # debug
  print "Accepted new connectionn";

  # 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 "$datan";
          }
          else {
            warn "$0: fdopen $value: $!";
          }
        }
      }
    }

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

close $listenSocket;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读