ソケット

ソケットは、他の通信手段に比べて多才な機能を持っている。 なぜなら、UNIX領域の狭いホスト内とインターネット領域の 広いネットーワーク内の両方で機能することができるためである。 通信指向のソケット(SOCK_STREAM)と接続されない ソケット(SOCK_DGRAM)の2つがサポートされている。 両方ともまずmake-socket-address関数で ソケットアドレスのオブジェクトを作らなければならない。 make-socket-addressは、socket-addressのインスタンスを返す。 UNIX領域では、ソケットアドレスにUNIXファイルシステム内のパス名を 入れる。 インターネット内では、ソケットアドレスに ホスト名とポート番号と必要ならプロトコル番号を結合 したものを入れる。 もし、ポート番号が/etc/servicesに定義されていれば、 service名によって指定されたsymbolを通して参照される。 unix:getservbyname関数がsymbol化されたservice名からポート番号を 引き出すために使用される。 1024より小さいポート番号は、rootユーザーのために予約されている。 特権のないユーザーは、1024より大きなポート番号を個人的なソケットとして 使用することを推奨する。

接続されたストリームは、両方向通信チャンネルとして供給されるが、 接続確定処理は、入力・出力で別々である。 片方がサーバーとして参照され、もう一方がクライアントとして参照される。 サーバーとなった端(service access point)は、最初に確定される。 これは、make-socket-port関数により作成される。 この関数は、socket-portのインスタンスを返す。 ソケットポートのオブジェクトは、make-server-socket-streamによって 1つまたは複数のクライアントからの接続を受けるために使用される。 make-server-socket-streamへの呼び出しは、クライアントからの 接続要求が実際に起こるまで実行待ち状態となる。 クライアントは、ソケットアドレスを指定することによって make-client-socket-streamでソケットストリーム を複数作ることができる。

;;; an example of IPC through a socket stream:
;;; server side
(setq saddr  (make-socket-address :domain af_inet :host "etlic2" :port 2000))
(setq sport  (make-socket-port saddr))
(setq sstream (make-server-socket-stream sport))
;;;
;;; client side
(setq caddr (make-socket-address :domain af_inet :host "etlic2" :port 2000))
(setq cstream (make-client-socket-stream caddr))

データベースや移動ロボットの環境シミュレータのようなアプリケーション では、1つのサーバーと複数のクライアント間の multiple connection service(多重接続サービス)が要求される。 この型のサーバーは、open-server関数によりプログラム することができる。 カレントホスト名と与えられたポート番号から open-serverは、接続要求にしたがってソケットポート(service access point) を作る。 このポートは非同期なので、 open-serverは遮断されず、直ちに返信する。 その後、接続要求はそれぞれEuslispのメインループを中断し、 ソケットストリーム が非同期に作成される。 このソケットストリームも非同期モードで働く。 open-serverの2番目の引き数にある非同期入力処理は、 新しいデータがこのストリームに現れたときはいつでも呼び出される。 30以上の接続が可能であるため、同時に多くのクライアントがサーバーの データにアクセスすることができる。

;; server side
(defun server-func (s) 
   (case (read s) ...    ;do appropriate jobs according to inputs
(open-server 3000 #'server-func)
... do other jobs in parallel
;; client-1 through client-N
(setq s (connect-server "etlmmd" 3000))
(format s "..." ...) (finish-output s)	;issue a command to the server
(read s)                                ;receive response

確実な通信チャンネルとして供給される接続指向 ストリームと対照的に 非接続 ソケットは、不確実な通信チャンネルである。 メッセージがなくなったり、重複したり、故障したりする可能性がある。 しかしながら、非接続 ソケットは、それぞれの接続にファイルディスクリプタを 割り当てる必要が無いし、 また、データやバッファのオーバーフローの読み込みをしないレシーバーでさえ 送信処理を中断することができないという利点がある。

非接続ソケットを作るためには、以下の命令を使用する。 メッセージはunix:sendtounix:recvfromによって変換される。

;;; receiver side
(setq saddr  (make-socket-address :domain af_inet :host "etlic2" :port 2001))
(setq sock   (make-dgram-socket saddr))
(unix:recvfrom sock)
;;;
;;; client side
(setq caddr (make-socket-address :domain af_inet :host "etlic2" :port 2001))
(setq sock (unix:socket (send caddr :domain) 2 0))
(unix:sendto sock caddr "this is a message")
;;;
;;; how to use echo service which is registered in /etc/services.
(setq caddr (make-socket-address :domain af_inet :host "etlic2"
                                 :port (car (unix:getservbyname "echo"))))
(setq echosock (unix:socket (send caddr :domain) 2 0))
(unix:sendto echosock caddr "this is a message")
(unix:recvfrom echosock)  --> "this is a messge"



make-socket-address &key :domain :pathname :host :port :proto :service [関数]

ソケットアドレスのオブジェクトを作る。


make-socket-port sockaddr [関数]

サーバー側のソケットポートを作る。 この関数は、クライアントとの接続を確立するために使用される。


make-server-socket-stream sockport &optional (size 100) [関数]

クライアントからの接続要求を受けて、双方向ストリームを返す。


make-client-socket-stream sockaddr &optional (size 100) [関数]

サーバーのポートと接続をし、双方向ストリームを返す。


open-server port remote-func [関数]

インターネット領域内でホスト名とportで指定されるソケットポートを 準備し、非同期に接続要求を待つ。 接続が要求されたとき、それを受け新しいソケットストリームがオープンされる。 ソケットポートにメッセージが到着したとき、remote-funcは、 ソケットポートを引き数として呼び出される。


connect-server host port [関数]

make-socket-addressmake-client-socket-streamを連続的に呼び出しを 行うための関数である。 hostportで指定されるソケットストリームを返す。このソケットストリーム は、クライアントがサーバーと通信を行うためのものである。 ポートは、インターネット領域内用に作られる。




2016-04-05