ラジコの録音、東京の放送を取得する一案(2 サーバークライアントの基本

2017年9月4日

ソケット通信を試します。
結構難しいのですが、以下のサンプルを使ってなんとかします。

要は、クライアントからチャンネル情報を送って、
サーバーからトークンを返すだけ、なのでこれで良いのです。

サーバー

さくらインターネットの方でサーバーを起動させます。

 

#!/usr/bin/perl

use strict;
use warnings;
use Socket;
use Fcntl qw(:flock);

# 2. 受付用ソケット情報の作成
my $local_port = 9000;

#ロック
open  LOCK , "+>" , "./serverlock.${local_port}";
if ( flock LOCK ,LOCK_EX|LOCK_NB ){
    print "OK LOCK!\n";
}else{
    print "NG LOCK!$!\n";
    exit ;
}

# サーバ

# 1. 受付用ソケットの作成

my $sock_receive;
socket($sock_receive, PF_INET, SOCK_STREAM, getprotobyname( 'tcp' ))
  or die "Cannot create socket: $!";


my $pack_addr = sockaddr_in($local_port, INADDR_ANY);

# 3. 受付用ソケットと受付用ソケット情報を結びつける
bind($sock_receive, $pack_addr)
  or die "Cannot bind: $!";

# 4. 接続を受け付ける準備をする。
listen($sock_receive, SOMAXCONN)
  or die "Cannot listen: $!";

# 5. 接続を受け付けて応答する。
my $sock_client; # クライアントとの通信用のソケット

while (accept( $sock_client, $sock_receive )) {
  my $content;
  
  # クライアントからのデータの読み込み
  while (my $line = <$sock_client>) {
    $content .= $line;
  }

  my $ret="Server."
  
  # クライアントへのデータの書き込み
  print $sock_client "$ret";
  close $sock_client;
}

$contentという変数にクライアントからのデータを取得できます。
クライアントにデータを戻すには、
print $sock_client “$ret";
で行っています。この例は単に「Server.」と返しています。

クライアント

ラズパイからクライアントを起動します。
サーバーに繋いでサーバーからデータを受け取ります。

#!/usr/bin/perl

use strict;
use Socket;

my $CH="";
if (@ARGV == 1){
    $CH=$ARGV[0];
}else{
    print "usage : ./$0 [CHANNEL]\n";
    exit 1;
}

# クライアント
# 1. ソケットの作成
my $sock;
socket($sock, PF_INET, SOCK_STREAM, getprotobyname('tcp' ))
  or die "Cannot create socket: $!";

# 2. ソケット情報の作成

# 接続先のホスト名
my $remote_host = 'サーバーのドメイン';
my $packed_remote_host = inet_aton($remote_host)
  or die "Cannot pack $remote_host: $!";

# 接続先のポート番号
my $remote_port = 9000;

# ホスト名とポート番号をパック
my $sock_addr = sockaddr_in($remote_port, $packed_remote_host)
  or die "Cannot pack $remote_host:$remote_port: $!";

# 3. ソケットを使って接続
connect($sock, $sock_addr)
  or die "Cannot connect $remote_host:$remote_port: $!";

# 4. データの書き込み
# 書き込みバッファリングをしない。
my $old_handle = select $sock;
$| = 1; 
select $old_handle;

print $sock "Hello";

# 書き込みを終了する
shutdown $sock, 1;

# 5. データの読み込み
my $cnt=0;
while (my $line = <$sock>) {
  print "$cnt $line";
  $cnt++;
}

# 6. ソケットを閉じる
close $sock;

サーバーにデータを送るには
print $sock “Hello";
でやっています。
そのあとの
print “$cnt $line";
でサーバーからの返答を受け取るというわけです。