LOCAL STREAM 型の通信


DGRAM型の接続はconnection less な接続でした。 そのため本当にデータが送られたのかがわかりません。 STREAM型の接続なら接続の確立が確認されているので データの転送が保証されています。

今度は LOCAL domain の LOCAL STREAM 型の通信を行ってみましょう。 これにも接続の目印となる UNIX domainソケットのファイルが必要です。 この通信方法は xserver や cannaserver などで使われています。


まずサーバー側のプログラムから見てみましょう。名前は localtcps.cc です。
LOCAL STREAM server : localtcps.cc のソースintegnet.h のソース

// LOCAL で STREAM なソケットによる通信プログラムの雛型 (サーバー側) #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include "integnet.h" // 接続の目印となるファイル #define SOCKNAME "/tmp/udsock" int main( void ) { // LOCAL で STREAM なソケットの作成 int sb = socket( AF_LOCAL, SOCK_STREAM, 0 ); // 接続の目印の指定 sockaddr_un addr = SOCKADDR_UN_INIT( AF_LOCAL, SOCKNAME ); // 古い目印の削除(もし残っていると厄介) unlink( SOCKNAME ); // 目印の公開 bind( sb, (sockaddr*)&addr, sizeof(addr) ); // 接続要求の受信開始(同時に1回線まで接続可とする) listen( sb, 1 ); // 接続要求の受信 int s = accept( sb, NULL, NULL ); // データの受信 char msg[64]; int len = recv( s, msg, sizeof(msg), 0 ); msg[len] = '\0'; // データの表示 printf("Server received : %s\n", msg ); // ソケットの廃止 close(s); close(sb); // 目印の削除(義務ではないが礼儀) unlink( SOCKNAME ); return 0; }

DGRAMの時よりも関数が増えました。ソケットは

int sb = socket( AF_LOCAL, SOCK_STREAM, 0 );
として LOCAL STREAM型で作成しています。

目印の作成とbindまでは同じですが、その次に listen関数があります。

listen( sb, 1 );
これでソケットはクライアントからのアクセスに聞き耳を立てる状態になります。 この引数 1 はこのソケットが同時に1つのクライアントの接続を受け付けることを 指定しています。この指定は後で紹介する多数のクライアントに同時に応対する サーバーを作る際に重要になります。

次にクライアントからのアクセスが来るの待って、 アクセスがあったらその接続を受け入れる accept関数を実行します。

int s = accept( sb, NULL, NULL );
accept関数が返す値は、そのクライアントとの通信用の新しいソケットです。 何かエラーが起こったり、acceptで待機中にシグナルを受けた場合にはacceptは -1 を 返します。acceptの第2第3引数にはクライアントに関する情報を受け取る変数を 指定するのですが、今回はその情報は受け取らないことにします。

以後はこのソケットを用いてデータの受信ができます。データの受信には recv関数を使います。

通信終了後にはこのソケットと、最初に作ったベースのソケットも閉じて下さい。


次にクライアント側のプログラムを見てみましょう。名前は localtcpc.cc です。
LOCAL STREAM client : localtcpc.cc のソース

// LOCAL で STREAM なソケットによる通信プログラムの雛型 (クライアント側) #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include "integnet.h" // 接続の目印となるファイル #define SOCKNAME "/tmp/udsock" int main( void ) { // LOCAL で STREAM なソケットの作成 int s = socket( AF_LOCAL, SOCK_STREAM, 0 ); // 通信開始のための目印の指定 sockaddr_un addr = SOCKADDR_UN_INIT( AF_LOCAL, SOCKNAME ); // ソケットの回線への接続 if( connect( s, (sockaddr*)&addr, sizeof(addr) ) < 0 ){ perror("connect"); exit(1); } // 送信するデータ char msg[64] = "This is client."; // データの送信 send( s, msg, sizeof(msg), 0 ); // 回線の切断 close(s); return 0; }

DGRAMのときとの違いは、connect関数を呼ぶことです。 これでサーバーへの接続が確固たるものになります。 データの送信にはsend関数を使います。send関数には送信先を 指定する変数は不要です。


目次

Copyright(C) by Naoki Watanabe. Jan 1st, 2001.
渡辺尚貴 naoki@cms.phys.s.u-tokyo.ac.jp