2016-12-12 29 views
1

私は、ローカルプログラムと外部のインタラクティブなWebサイトの間の「中間者」として働くperlスクリプトを持っています。Perl、無限ループのwebsocket

問題は、外部Webサイトがプレーンtcp接続からWebsocket接続に移行したことです。

初期接続後、クライアント(スクリプト)とサーバー(外部Webサイト)がハンドシェイクを行い、スクリプトがユーザー名とパスワードを送信し、サーバーが最後に応答しますその後、スクリプトは無限ループに入り、両方の接続からのデータを待ってから、そのデータを処理し、必要に応じて接続に「印刷」します。

Mojo :: UserAgentとprotocol :: websocketを使用してサーバーとwebsocket接続を確立できましたが、ハンドシェイクと他の情報交換(ユーザー名、パスワードなど)を経由しますが、私はIO :: Selectを使って無限ループにwebsocket接続を "スロー"することができませんでした。他の提案は間違いなく歓迎されています)。 、私は発見した無限ループの例

# Creating connection for local program 
$lsn=new IO::Socket::INET(
    Proto => 'tcp', 
    LocalPort => 6000, 
    Listen => 1, 
); 
unless(defined $lsn){ 
    print"$0: $!\n"; 
    exit 1; 
} 
print"Waiting for local program connection on port 6000\n"; 
$server=$lsn->accept; 
$lsn->close; 
unless(defined $server){ 
    print "$0: Unable to accept incoming connection: $!\n"; 
    exit 1; 
    } 
# At this point, the script is waiting for a connection from 
# the local program on port 6000 
printf"Connection accepted from %s\n",$server->peerhost; 
select $server; 
binmode $server; 
$stdin=$server; 
(select)->autoflush(1); 
# Creating connection for external website 
$net=new IO::Socket::INET(
    Proto => 'tcp', 
    PeerAddr => $yog, 
    PeerPort => $yserverport, 
); 

unless(defined($net)){ 
    print "Can't connect!\n"; 
    exit 1; 
} 
$net->autoflush(1); 
#################################### 
# Here the script and server will # 
# exchange information few times # 
#################################### 
my $sel=new IO::Select($stdin,$net); 
$net->autoflush(0); 
while (1){ 
    foreach my $i($sel->can_read(0.05)){ 
     if($i==$net){ 
      &dosomething; 
      $net->flush; 
     } 
     else{ 
      &dosomething2; 
      $net->flush; 
     } 
    } 
} 

Iが着信データをチェックすることができる無限ループを使用する必要があるので、この場合には適していない。

スクリプトの関連部分は以下の通りです。両方の接続で。

答えて

0

WebSocketは、IOソケットを大幅に必要とします。彼らはハンドシェイクとデータフレーミングが必要です。私はW3C WebSocket APIを見直し、重い作業をするためにperlモジュール(Net::WebSocket::Server)を使用して調べます。また、WebSocketはSSLを使用するクロムブラウザでしか動作しませんので、相互互換性に関心がある場合は、代わりにIO :: Socket :: SSLでNet :: WebSocket :: Serverを使用してください。

#!/usr/bin/perl 
use strict; 
use warnings; 
use IO::Socket::SSL; 
use Net::WebSocket::Server; 

my $ssl_server = IO::Socket::SSL->new(
     Listen  => 5, 
     LocalPort  => 4000, 
     Proto   => 'tcp', 
     SSL_cert_file => '/var/ssl/cert.crt', 
     SSL_key_file => '/var/ssl/cert.key', 
    ) or die "failed to listen: $!"; 

my $port = 6000; 
my $origin = 'https://YOURDOMAIN.com'; 

Net::WebSocket::Server->new(
    listen => $ssl_server, 

    on_connect => sub { 
      our ($serv, $conn) = @_; 
      $conn->on(

      handshake => sub { 
         my ($conn, $handshake) = @_; 
         $conn->disconnect() unless $handshake->req->origin eq $origin; 
        }, 
        utf8 => sub { 

      my ($conn, $msg) = @_; 
      my $MyIP = $conn->ip(); 
      my $MyPORT = $conn->port(); 
      $_->send_utf8($msg) for($serv->connections()); 
       }, 
    ); 
    }, 
)->start; 

あなたはクロームまたはここSSLと心配していない場合は(それは厳格な使用と警告を使用する必要があります)、ワーキング非SSLの例である:

また
#!/usr/bin/perl 

use Net::WebSocket::Server; 

my $port = 6000; 

Net::WebSocket::Server->new(
    listen => $port, 
    on_connect => sub { 
     my ($serv, $conn) = @_; 
     $conn->on(
      utf8 => sub { 
     my ($conn, $msg) = @_; 
       $_->send_utf8($msg) for($serv->connections()); 
      }, 
     ); 
    }, 
)->start; 

あなたはSSLバージョンを使用することにした場合、作りますクライアント側をws://からwss://

+0

に更新する必要がありますが、スクリプトはac lientスクリプトやプログラムでは、websocketスクリプトは実際には独自の「サーバ」なので、コマンドラインから呼び出すことができます。 "perl myscript.pl"とCTL + Cをキャンセルします。バックグラウンドでスクリプトを実行する場合は、スクリプトをサービスとして登録する必要があります。これはOSによって異なります。他にも少なくともLinuxでは "perl myscript.pl nohup&"を実行してコマンドラインから実行し、ターミナルにエスケープすることができます。私はこれが役立つことを願っています – Bryan