Perl-ソケットプログラミング

ソケットとは何ですか?

Socketは、異なるプロセス間に仮想二重接続を作成するBerkeleyUNIXメカニズムです。これは後にすべての既知のOSに移植され、異なるOSソフトウェアで実行されている地理的な場所にまたがるシステム間の通信を可能にしました。ソケットがなければ、システム間のネットワーク通信のほとんどは決して起こらなかったでしょう。

よく見てください。ネットワーク上の一般的なコンピュータシステムは、その上で実行されているさまざまなアプリケーションの必要に応じて情報を送受信します。一意のIPアドレスが指定されているため、この情報はシステムにルーティングされます。システムでは、この情報は、さまざまなポートでリッスンする関連アプリケーションに提供されます。たとえば、インターネットブラウザは、Webサーバーから受信した情報をポート80でリッスンします。また、特定のポート番号で情報をリッスンおよび送受信できるカスタムアプリケーションを作成することもできます。

とりあえず、ソケットはIPアドレスとポートであり、接続がネットワークを介してデータを送受信できるようにすることを要約しましょう。

上記のソケットの概念を説明するために、クライアントの例を取り上げます-Perlを使用したサーバープログラミング。クライアントサーバーアーキテクチャを完成させるには、次の手順を実行する必要があります-

サーバーを作成するには

  • を使用してソケットを作成します socket コール。

  • を使用してソケットをポートアドレスにバインドします bind コール。

  • を使用してポートアドレスでソケットをリッスンします listen コール。

  • を使用してクライアント接続を受け入れる accept コール。

クライアントを作成するには

  • でソケットを作成します socket コール。

  • を使用して(ソケット)をサーバーに接続します connect コール。

次の図は、クライアントとサーバーが相互に通信するために使用する呼び出しの完全なシーケンスを示しています。

サーバー側のソケット呼び出し

socket()呼び出し

ザ・ socket()呼び出しは、ネットワーク接続を確立する最初の呼び出しであり、ソケットを作成します。この呼び出しの構文は次のとおりです-

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

上記の呼び出しはSOCKETを作成し、他の3つの引数は整数であり、TCP / IP接続に対して次の値を持つ必要があります。

  • DOMAINPF_INETである必要があります。お使いのコンピュータではおそらく2です。

  • TYPE TCP / IP接続の場合はSOCK_STREAMである必要があります。

  • PROTOCOL する必要があります (getprotobyname('tcp'))[2]。ソケットを介して話されるのは、TCPなどの特定のプロトコルです。

したがって、サーバーによって発行されるソケット関数呼び出しは次のようになります-

use Socket     # This defines PF_INET and SOCK_STREAM

socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);

bind()呼び出し

socket()呼び出しによって作成されたソケットは、ホスト名とポート番号にバインドされるまで役に立ちません。サーバーは以下を使用しますbind() クライアントからの接続を受け入れるポートを指定する関数。

bind( SOCKET, ADDRESS );

ここで、SOCKETはsocket()呼び出しによって返される記述子であり、ADDRESSは3つの要素を含むソケットアドレス(TCP / IPの場合)です。

  • アドレスファミリ(TCP / IPの場合、AF_INET、おそらくシステムでは2)。

  • ポート番号(たとえば21)。

  • コンピューターのインターネットアドレス(たとえば、10.12.12.168)。

bind()はサーバーによって使用されるため、サーバーは自身のアドレスを知る必要がないため、引数リストは次のようになります。

use Socket        # This defines PF_INET and SOCK_STREAM

$port = 12345;    # The unique port used by the sever to listen requests
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't bind to port $port! \n";

ザ・ or die サーバーが未処理の接続なしで停止した場合、オプションSO_REUSEADDRを使用しない限り、ポートはすぐに再利用できないため、この句は非常に重要です。 setsockopt()関数。ここにpack_sockaddr_in() 関数は、ポートとIPアドレスをバイナリ形式にパックするために使用されています。

listen()呼び出し

これがサーバープログラムの場合は、に呼び出しを発行する必要があります listen()指定されたポートでリッスンします。つまり、着信要求を待ちます。この呼び出しの構文は次のとおりです-

listen( SOCKET, QUEUESIZE );

上記の呼び出しは、socket()呼び出しによって返されるSOCKET記述子を使用します。QUEUESIZEは、同時に許可される未処理の接続要求の最大数です。

accept()呼び出し

これがサーバープログラムの場合は、に呼び出しを発行する必要があります access()着信接続を受け入れる機能。この呼び出しの構文は次のとおりです-

accept( NEW_SOCKET, SOCKET );

accept呼び出しはsocket()関数によって返されるSOCKET記述子を受信し、正常に完了すると、クライアントとサーバー間の今後のすべての通信のために新しいソケット記述子NEW_SOCKETが返されます。access()呼び出しが失敗すると、最初に使用したSocketモジュールで定義されているFLASEが返されます。

一般に、accept()は無限ループで使用されます。1つの接続が到着するとすぐに、サーバーはそれを処理するための子プロセスを作成するか、それを自分で提供してから、さらに接続をリッスンするために戻ります。

while(1) {
   accept( NEW_SOCKET, SOCKT );
   .......
}

これで、サーバーに関連するすべての呼び出しが終了し、クライアントが必要とする呼び出しを確認できます。

クライアント側のソケット呼び出し

connect()呼び出し

クライアントプログラムを準備する場合は、最初に使用します socket() ソケットを作成するために呼び出すと、使用する必要があります connect()サーバーに接続するために呼び出します。すでにsocket()呼び出しの構文を見てきましたが、サーバーのsocket()呼び出しと同様のままですが、次の構文は次のとおりです。connect() 呼び出し-

connect( SOCKET, ADDRESS );

ここで、SCOKETは、クライアントによって発行されたsocket()呼び出しによって返されるソケット記述子であり、ADDRESSは、リモートサーバーのIPアドレスが含まれていることを除いて、バインド呼び出しと同様のソケットアドレスです。

$port = 21;    # For example, the ftp port
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't connect to port $port! \n";

サーバーに正常に接続できれば、SOCKET記述子を使用してサーバーへのコマンドの送信を開始できます。そうしないと、エラーメッセージが表示されてクライアントが出てきます。

クライアント-サーバーの例

以下は、Perlソケットを使用して単純なクライアントサーバープログラムを実装するためのPerlコードです。ここで、サーバーは着信要求をリッスンし、接続が確立されると、サーバーからSmileに応答するだけです。クライアントはそのメッセージを読み、画面に印刷します。サーバーとクライアントが同じマシン上にあると仮定して、それがどのように行われたかを見てみましょう。

サーバーを作成するためのスクリプト

#!/usr/bin/perl -w
# Filename : server.pl

use strict;
use Socket;

# use port 7890 as default
my $port = shift || 7890;
my $proto = getprotobyname('tcp');
my $server = "localhost";  # Host IP running the server

# create a socket, make it reusable
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "Can't open socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "Can't set socket option to SO_REUSEADDR $!\n";

# bind to a port, then listen
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't bind to port $port! \n";

listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port\n";

# accepting a connection
my $client_addr;
while ($client_addr = accept(NEW_SOCKET, SOCKET)) {
   # send them a message, close connection
   my $name = gethostbyaddr($client_addr, AF_INET );
   print NEW_SOCKET "Smile from the server";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

サーバーをバックグラウンドモードで実行するには、Unixプロンプトで次のコマンドを発行します-

$perl sever.pl&

クライアントを作成するためのスクリプト

!/usr/bin/perl -w
# Filename : client.pl

use strict;
use Socket;

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "localhost";  # Host IP running the server

# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "Can't create a socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't connect to port $port! \n";

my $line;
while ($line = <SOCKET>) {
   print "$line\n";
}
close SOCKET or die "close: $!";

次に、コマンドプロンプトでクライアントを起動します。コマンドプロンプトはサーバーに接続し、サーバーから送信されたメッセージを読み取り、次のように画面に表示します。

$perl client.pl
Smile from the server

NOTE −実際のIPアドレスをドット表記で指定する場合は、混乱を避けるために、クライアントとサーバーの両方で同じ形式のIPアドレスを指定することをお勧めします。