情報学類 分散システム 2008年12月16日
筑波大学システム情報工学研究科
コンピュータサイエンス専攻, 電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2008/2008-12-16
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
main() {
connect(); // 結合が作られる通信プリミティブを使う時
marshal();
send();
receive();
unmarshal();
close(); // 結合が作られる通信プリミティブを使う時
}
main()
make_port(); // 結合が作られる通信プリミティブを使う時
while( 1 )
{
accept(); // 結合が作られる通信プリミティブを使う時
receive();
unmarshal();
仕事();
marshal();
send();
close(); // 結合が作られる通信プリミティブを使う時
}
}
marshaling のことを Java 用語では、serialize という。
今後 TCP/IP 以外にも様々な通信プロトコルが開発され、Unix で利用できる ように設計されている。TCP/IP で使う時には、煩雑である。
int socket = socket(int domain, int type, int protocol)
主に domain と type で利用するプロトコルを指定する。
最後の引数 protocol は、普段は 0 を指定する。
| ドメイン(domain) | 型(type) | プロトコル(protocol) |
| PF_INET | SOCK_STREAM | TCP(IPv4) |
| PF_INET | SOCK_DGRAM | UDP(IPv4) |
| PF_INET6 | SOCK_STREAM | TCP(IPv6) |
| PF_INET6 | SOCK_DGRAM | UDP(IPv6) |
| PF_UNIX | SOCK_STREAM | 同一ホスト内(UNIXドメイン)のストリーム |
| PF_UNIX | SOCK_DGRAM | 同一ホスト内(UNIXドメイン)のデータグラム |
| PF_NS | SOCK_STREAM | XNS のストリーム(SPP) |
| PF_NS | SOCK_SEQPACKET | XNS の順序付きパケット(IDP) |
| PF_NS | SOCK_RDM | XNSの信頼性のあるデータグラム(SPP) |
| 名前 | 説明 |
| socket() | 通信プロトコルに対応したソケット・オブジェクトを作成する |
| connect() | 結合(conection)を確立させる。サーバのアドレスを固定する。 |
| listen() | サーバ側で接続要求の待ち受けを開始する。 |
| accept() | サーバ側で接続されたソケットを得る。 |
| bind() | ソケットにアドレス(名前)を付ける。 |
| getpeername() | 通信相手のアドレス(名前)を得る。 |
| getsockname() | 自分のアドレス(名前)を得る。 |
| send(), sendto(), sendmsg() | メッセージを送信する。 |
| recv(), recvfrom(), recvmsg() | メッセージを受信する。 |
| shutdown() | 双方向の結合を部分的に切断する。 |
| getsockopt() | オプションの現在の値を取得する。 |
| setsockopt() | オプションを設定する。 |
| select(), poll() | 複数の入出力(通信を含む)を多重化する。 |
| write() | メッセージを送信する。 |
| read() | メッセージを受信する。 |
| close() | ファイル記述子を閉じる。他に参照しているファイル記述子がなければ、ソケット・オブジェクトを削除する。 |
| 名前 | 説明 |
| gethostbyname() | ホスト名から IP アドレスを調べる。 |
| getaddrinfo() | ホスト名から IP アドレスを調べる。IPv6対応。 |
| gethostbyaddr() | IPアドレスからホスト名を調べる。 |
| getnameinfo() | IPアドレスからホスト名を調べる。IPv6対応。 |
| freeaddrinfo() | getaddrinfo(), getnameinfo() で得られた構造体を解放する。 |
tcp_acc_port( int portno ) (サーバ側)
int tcp_connect( char *server, int portno ) (クライアント側)
accept() をそのまま使う。
accept() は、1つのクライアントから接続要求を受け付ける。
第1引数の socket は、tcp_acc_port() で作成したソケットを渡す。
TCP/IP では、クラ イアント側とサーバ側でソケット・オブジェクトの作成するクラスが違ってい る。
| クラス名 | 説明 |
|---|---|
| Socket | TCP/IP のクライアント側のソケット |
| ServerSocket | TCP/IP のサーバ側のソケット |
| DatagramSocket | UDP/IP のソケット |
以後、ネットワークか ら文字列を入力するには、InputStreamReader や BufferedReader のオブジェ クトを生成して利用する。
出力側では、Socket クラスのオブジェクトに対して getOutputStream() して、 OutputStream クラスのオブジェクトを得て、 PrintStream オブジェクトを生成して利用できる。

図? ネットワークOSでのアプリケーションの実行
ライブラリの機能。クライアントとして働く。 サーバは、サーバ server のポート番号 portno で動作している。get_highscore_client(char *server, int portno, score_record_t records[], int len )
score_record_t型)を最大 len 個だけ取得する。
実際に保存していた数を返す。
int put_score_client(char *server, int portno, int score, char *user)
.」を忘れないように。
% mkdir hiscore-tcp
% cd hiscore-tcp
% cp ~yas/dsys/highscore/tcp/add-hiscore.c .
% cp ~yas/dsys/highscore/tcp/highscore-client.c .
% cp ~yas/dsys/highscore/tcp/highscore-server.c .
% cp ~yas/dsys/highscore/tcp/highscore-tcp.h .
% cp ~yas/dsys/highscore/tcp/marshaling-burffer.c .
% cp ~yas/dsys/highscore/tcp/marshaling-burffer.h .
% cp ~yas/dsys/highscore/tcp/show-hiscore.c .
% cp ~yas/dsys/highscore/tcp/Makefile .
% ls
Makefile highscore-server.c marshaling-burffer.h
add-hiscore.c highscore-tcp.h show-hiscore.c
highscore-client.c marshaling-burffer.c
%
% make
cc -g -c -o add-hiscore.o add-hiscore.c
cc -g -c -o highscore-client.o highscore-client.c
cc -g -c -o marshaling-burffer.o marshaling-burffer.c
cc -g add-hiscore.o highscore-client.o marshaling-burffer.o -o add-hiscore
cc -g -c -o show-hiscore.o show-hiscore.c
cc -g show-hiscore.o highscore-client.o marshaling-burffer.o -o show-hiscore
cc -g -c -o highscore-server.o highscore-server.c
cc -g highscore-server.o marshaling-burffer.o -o highscore-server
% ls
Makefile highscore-server marshaling-burffer.o
add-hiscore highscore-server.c show-hiscore
add-hiscore.c highscore-server.o show-hiscore.c
add-hiscore.o highscore-tcp.h show-hiscore.o
highscore-client.c marshaling-burffer.c
highscore-client.o marshaling-burffer.h
%
make コマンドを実行すると、Makefile の記述に従い3つの実行
形式のファイル highscore-server,
add-hiscore, add-hiscore が作られる。
例題を実行するには、クライアント用とサーバ用に端末を2つ開く。
その方法は、make help で表示される。
% make help
Open two terminals for server and client
server:
./highscore-server portno
(To stop this server, Press ^C)
client:
./add-hiscore server portno score name
./show-hiscore server portno num
%
クライアントとサーバは、別のコンピュータで動作させても良い。 以下の例では、サーバをazalea20 で動作させている。 サーバ側:
% ssh azalea20
% cd hiscore-tcp/
% ./highscore-server
Usage: % ./highscore-server portno
% ./highscore-server 1231
run client azalea20 1231
(To stop this server, Press ^C)
サーバは終了しないので、実験が終わったら ^C で止める。
クライアント側は、もう1つの端末で実行する。
% ./add-hiscore
Usage: % ./add-hiscore server portno score "User Name"
% ./add-hiscore azalea20 1231 10 "Yasushi Shinjo"
% ./add-hiscore azalea20 1231 20 "Kazuhiko Kato"
% ./show-hiscore
Usage: % ./show-hiscore host portno n
% ./show-hiscore azalea20 1231 10
2 hiscore record(s) received
20 Kazuhiko Kato
10 Yasushi Shinjo
%
実験が終了したら、サーバを ^C コマンドで削除する。
% ./highscore-server 1231
run client azalea20 1231
(To stop this server, Press ^C)
[11418] connection (fd==4) from 130.158.86.207:60898
[11418] connection (fd==4) from 130.158.86.207:60900
[11418] connection (fd==4) from 130.158.86.207:60903
^C
%

図? クライアント・サーバ間で交わされる要求メッセージと応答メッセージ
hiscoreで用いる要求メッセージの形式
図? 要求メッセージの例

図? 応答メッセージの例
1:
2: /*
3: highscore-tcp.h -- Hiscore Protocol over TCP
4: Created on: 2008/12/05 19:06:01
5: ~/dsys/highscore/tcp/highscore-proto.h
6: */
7:
8: #ifndef _HIGHSCORE_TCP_H_
9: #define _HIGHSCORE_TCP_H_
10:
11: #define HISCORE_PROTO_MAX_MESSAGE_SIZE 1024
12:
13: #define HISCORE_PROTO_GET_HISCORE 1
14: #define HISCORE_PROTO_PUT_SCORE 2
15:
16: #define HISCORE_PROTO_OK 0
17: #define HISCORE_PROTO_NO_COMMAND -1
18: #define HISCORE_PROTO_MARSHAL_ERROR -2
19:
20: #define HIGHSCORE_MAX_RECORDS 10
21: #define HIGHSCORE_NAME_LEN 28
22:
23: struct score_record {
24: int score;
25: char name[HIGHSCORE_NAME_LEN];
26: };
27: typedef struct score_record score_record_t;
28:
29: /* for clients */
30: extern int get_highscore_client(char *server, int portno,
31: score_record_t records[], int len );
32: extern int put_score_client(char *server, int portno, int score, char *user);
33:
34: #endif _HIGHSCORE_TCP_H_
score_record_tで表現する。
この構造体は、全体で32バイトある。の最初の4バイトは、整数型で、得点、残
りの28バイトは、文字の配列。ASCII で最大27文字まで保存できる。文字が含
まれない部分は、0が入る。
score_record_t 型の配列で表す。
get_highscore_client() と
put_score_client がある。

図?モジュールの構成
int marbuf_init( marbuf_t *mb, size_t len )
void marbuf_final( marbuf_t *mb )
int marbuf_receive_message( marbuf_t *mb, int socket )
int marbuf_send_message( marbuf_t *mb, int socket )
int marbuf_marshal_int( marbuf_t *mb, int data )
int marbuf_unmarshal_int( marbuf_t *mb, int *datap )
int marbuf_marshal_byte_array( marbuf_t *mb, char data[], int data_len )
int marbuf_unmarshal_byte_array( marbuf_t *mb, char data[], int data_len )
marbuf_t message; int x;
marbuf_init( &message, MAX_MESSAGE_SIZE );
marbuf_marshal_int( &message, x );
marbuf_send_message( &message, socket );
marbuf_final( &message, socket );
基本的な使い方: メッセージの受信とアンマーシャリング
marbuf_t message; int x;
marbuf_init( &message, MAX_MESSAGE_SIZE );
marbuf_receive_message( &message, socket );
marbuf_unmarshal_int( &message, &x );
marbuf_final( &message, socket );
put_score_client() 関数を呼び出す簡単なプログラム。
1:
2: /*
3: add-hiscore.c -- The main function of put_score_client().
4: Created on: 2008/12/06 17:47:08
5: ~yas/dsys/highscore/tcp/add-hiscore.c
6: */
7:
8: #include <stdio.h> /* stderr, fprintf() */
9: #include <stdlib.h> /* strtol() */
10: #include "highscore-tcp.h"
11:
12: void usage( char *comname ) {
13: fprintf(stderr,"Usage: %% %s server portno score \"User Name\"\n", comname);
14: exit( 1 );
15: }
16:
17: main( int argc, char *argv[], char *envp[] ) {
18: int score, portno ;
19: char *name, *server ;
20: if( argc != 5 )
21: usage( argv[0] );
22: server = argv[1];
23: portno = strtol( argv[2], 0, 10);
24: score = strtol( argv[3], 0, 10);
25: name = argv[4];
26: put_score_client( server, portno, score, name );
27: }
put_score_client()関数を呼び出す。
get_hiscore_client() 関数を呼び出す簡単なプログラム。
1:
2: /*
3: show-hiscore.c -- The main function for get_highscore_client().
4: Created on: 2008/12/06 19:21:52
5: ~yas/dsys/highscore/centralized/show-hiscore.c
6: */
7:
8: #include <stdio.h> /* stderr, fprintf() */
9: #include <stdlib.h> /* strtol() */
10: #include "highscore-tcp.h"
11:
12: static void show_score( char *host, int port, int top );
13:
14: static void usage( char *comname ) {
15: fprintf(stderr,"Usage: %% %s host portno n\n", comname);
16: exit( 1 );
17: }
18:
19: main( int argc, char *argv[], char *envp[] ) {
20: int top, portno ;
21: char *name, *server ;
22: if( argc != 4 )
23: usage( argv[0] );
24: server = argv[1];
25: portno = strtol( argv[2], 0, 10);
26: top = strtol( argv[3], 0, 10);
27: show_score( server, portno, top );
28: }
29:
30: static void show_score( char *server, int portno, int top ) {
31: score_record_t records[HIGHSCORE_MAX_RECORDS];
32: int n, i ;
33: if( top > HIGHSCORE_MAX_RECORDS ) {
34: fprintf(stderr,"Warning: top too large: %d\n",top);
35: top = HIGHSCORE_MAX_RECORDS;
36: }
37: n = get_highscore_client( server, portno, records, top );
38: if( n >= 0 ) {
39: printf("%d hiscore record(s) received\n", n );
40: for( i=0; i<n; i++ ) {
41: printf("%10d %s\n", records[i].score, records[i].name );
42: }
43: }
44: else {
45: printf("error: %d\n", n );
46: }
47: }
put_score_client()関数を呼び出す。
1: 2: /* 3: highscore-client.c -- The hiscore client using TCP/IP stream. 4: Created on: 2008/12/06 17:03:28 5: ~yas/dsys/highscore/tcp/highscore-client.c 6: */ 7: 8: #include <stdio.h> /* stderr, fprintf() */ 9: #include <stdlib.h> /* strtol() */ 10: #include <string.h> /* memcpy() */ 11: #include <sys/types.h> /* socket() */ 12: #include <sys/socket.h> /* socket() */ 13: #include <netinet/in.h> /* struct sockaddr_in */ 14: #include <netdb.h> /* getaddrinfo(), freeaddrinfo(), struct addrinfo */ 15: #include "highscore-tcp.h" 16: #include "marshaling-burffer.h" 17: 18: /* From Coins System Program */ 19: extern int tcp_connect( char *server, int portno ); 20: extern int sockaddr_in_init( struct sockaddr_in *addr, int addrlen, 21: char *hostname, int portno ); 22:
tcp_connect() と sockaddr_in_init()
を使う。
23: int get_highscore_client( char *server, int portno,
24: score_record_t records[], int len ) {
25: int sock, cmd, n, i;
26: marbuf_t request, reply;
27: marbuf_init( &request,HISCORE_PROTO_MAX_MESSAGE_SIZE );
28: marbuf_init( &reply,HISCORE_PROTO_MAX_MESSAGE_SIZE );
29: if( !marbuf_marshal_int( &request, HISCORE_PROTO_GET_HISCORE ) )
30: goto error0;
31: marbuf_marshal_int( &request, len );
32: if( (sock = tcp_connect( server, portno )) < 0 ) {
33: perror("tcp_sonnect");
34: goto error0;
35: }
36: if( marbuf_send_message( &request, sock ) < 0 ) {
37: perror("send");
38: goto error1;
39: }
40: if( marbuf_receive_message( &reply, sock ) < 0 ) {
41: perror("recieve");
42: goto error1;
43: }
44: if( !marbuf_unmarshal_int( &reply, &n ) ) {
45: fprintf(stderr,"unmarshal n\n");
46: goto error1;
47: }
48: if( n > len ) {
49: fprintf(stderr,"received message too large: %d > %d\n", n, len );
50: goto error1;
51: }
52: for( i=0 ; i<n; i++ ) {
53: if( !marbuf_unmarshal_int(&reply,&records[i].score ) ) {
54: fprintf(stderr,"unmarshal name\n");
55: goto error1;
56: }
57: if( !marbuf_unmarshal_byte_array(&reply,records[i].name,
58: HIGHSCORE_NAME_LEN) ) {
59: fprintf(stderr,"unmarshal name\n");
60: goto error1;
61: }
62: }
63: close( sock );
64: marbuf_final( &request );
65: marbuf_final( &reply );
66: return( n );
67:
68: error1: close( sock );
69: error0: marbuf_final( &request );
70: marbuf_final( &reply );
71: return( -1 );
72: }
73:
74: int put_score_client(char *server, int portno, int score, char *name) {
75: int sock, cmd, ok;
76: marbuf_t request, reply;
77: char name_buf[HIGHSCORE_NAME_LEN];
78: marbuf_init( &request,HISCORE_PROTO_MAX_MESSAGE_SIZE );
79: marbuf_init( &reply,HISCORE_PROTO_MAX_MESSAGE_SIZE );
80: if( !marbuf_marshal_int( &request, HISCORE_PROTO_PUT_SCORE) )
81: goto error0;
82: if( !marbuf_marshal_int( &request, score ) )
83: goto error0;
84: memset( name_buf, 0, HIGHSCORE_NAME_LEN );
85: snprintf( name_buf, HIGHSCORE_NAME_LEN, "%s", name );
86: if( !marbuf_marshal_byte_array( &request, name_buf, HIGHSCORE_NAME_LEN ) )
87: goto error0;
88: if( (sock = tcp_connect( server, portno )) < 0 ) {
89: perror("tcp_sonnect");
90: goto error0;
91: }
92: if( marbuf_send_message( &request, sock ) < 0 ) {
93: perror("send");
94: goto error1;
95: }
96: if( marbuf_receive_message( &reply, sock ) < 0 ) {
97: perror("recieve");
98: goto error1;
99: }
100: if( !marbuf_unmarshal_int( &reply, &ok ) ) {
101: fprintf(stderr,"unmarshal n\n");
102: goto error1;
103: }
104: close( sock );
105: marbuf_final( &request );
106: marbuf_final( &reply );
107: return( ok );
108:
109: error1: close( sock );
110: error0: marbuf_final( &request );
111: marbuf_final( &reply );
112: return( -1 );
113: }
114:
115: /* From Coins System Program */
116: int tcp_connect( char *server, int portno ) {
...
136: int sockaddr_in_init( struct sockaddr_in *addr, int addrlen,
137: char *hostname, int portno ) {
...
1:
2: /*
3: highscore-server.c -- The hiscore server using TCP/IP stream.
4: Created on: 2008/12/05 18:56:11
5: ~yas/dsys/highscore/tcp/highscore-server.c
6: */
7:
8: #include <stdio.h> /* stderr, fprintf() */
9: #include <stdlib.h> /* strtol() */
10: #include <string.h> /* memcpy() */
11: #include <sys/types.h> /* socket() */
12: #include <sys/socket.h> /* socket() */
13: #include <netinet/in.h> /* struct sockaddr_in, INADDR_ANY */
14: #include <netdb.h> /* getnameinfo() */
15: #include "highscore-tcp.h"
16: #include "marshaling-burffer.h"
17:
18: /* From Coins System Program */
19: extern int tcp_acc_port( int portno );
20: extern void tcp_peeraddr_print( int com );
21: extern void sockaddr_print( struct sockaddr *addrp, socklen_t addr_len );
22: extern int tcp_acc_port( int portno );
23:
24: /* Hiscore data in memory */
25: static score_record_t hiscore_records[HIGHSCORE_MAX_RECORDS];
26: static int hiscore_nelements;
27:
28: static void hiscore_server( int portno );
29: static void hiscore_request_reply( int com );
30: static void print_my_host_port( int portno );
31: static int insert_score( score_record_t records[], int len, int nelement,
32: int score, char *user );
33: static int find_posision( score_record_t records[], int len, int nelement,
34: int score );
35:
36: static void usage( char *comname ) {
37: fprintf(stderr,"Usage: %% %s portno\n", comname);
38: exit( 1 );
39: }
40:
41: main( int argc, char *argv[], char *envp[] ) {
42: int portno;
43: if( argc != 2 )
44: usage( argv[0] );
45: portno = strtol( argv[1], 0, 10 );
46: hiscore_server( portno );
47: }
48:
tcp_acc_port(), tcp_peeraddr_print() ,
sockaddr_print() を使う。
hiscore_records[]にハイスコアのデータを保持する。
その要素数は、hiscore_nelementsに保持する。
main() は、文字列でポート番号を引数にとり、それを整数にして
hiscore_server() を呼び出す。
49: static void hiscore_server( int portno ) {
50: int acc,com ;
51: acc = tcp_acc_port( portno );
52: if( acc<0 )
53: exit( -1 );
54: print_my_host_port( portno );
55: printf("(To stop this server, Press ^C)\n");
56: while( 1 ) {
57: if( (com = accept( acc,0,0 )) < 0 ) {
58: perror("accept");
59: exit( -1 );
60: }
61: tcp_peeraddr_print( com );
62: hiscore_request_reply( com );
63: }
64: }
65:
tcp_acc_port() で、接続受付の準備をする。
accept() で、1つのクライアントから接続を受け付ける。
hiscore_request_reply() で、要求の受信と応答の送信を行う。
66: static void hiscore_request_reply( int com ) {
67: marbuf_t request, reply;
68: int cmd;
69: marbuf_init( &request,HISCORE_PROTO_MAX_MESSAGE_SIZE );
70: marbuf_init( &reply,HISCORE_PROTO_MAX_MESSAGE_SIZE );
71: if( marbuf_receive_message( &request, com ) < 0 ) {
72: perror("read");
73: goto error0;
74: }
75:
76: if( !marbuf_unmarshal_int( &request, &cmd ) ) {
77: perror("request_msg cmd");
78: goto error0;
79: }
80: switch( cmd ) {
81: case HISCORE_PROTO_PUT_SCORE:
82: {
83: int score ; char name[HIGHSCORE_NAME_LEN];
84: if( !marbuf_unmarshal_int( &request, &score ) )
85: goto error1;
86: if( !marbuf_unmarshal_byte_array( &request, name, HIGHSCORE_NAME_LEN ) )
87: goto error1;
88: hiscore_nelements = insert_score( hiscore_records, HIGHSCORE_MAX_RECORDS,
89: hiscore_nelements, score, name );
90: if( !marbuf_marshal_int( &reply, HISCORE_PROTO_OK ) )
91: goto error1;
92: break;
93: }
94: case HISCORE_PROTO_GET_HISCORE:
95: {
96: int len,i,n ;
97: if( !marbuf_unmarshal_int( &request, &len ) )
98: goto error1;
99: if( len > HIGHSCORE_MAX_RECORDS )
100: len = HIGHSCORE_MAX_RECORDS;
101: n = len < hiscore_nelements ? len : hiscore_nelements ;
102: /* return n and hiscore_records[0..n-1] to client. */
103: if( !marbuf_marshal_int( &reply, n ) )
104: goto error1;
105: for( i=0 ; i<n; i++ )
106: {
107: if( !marbuf_marshal_int( &reply,hiscore_records[i].score ) )
108: goto error1;
109: if( !marbuf_marshal_byte_array(
110: &reply,hiscore_records[i].name,HIGHSCORE_NAME_LEN ) )
111: goto error1;
112: }
113: break;
114: }
115: default:
116: marbuf_marshal_int( &reply, HISCORE_PROTO_NO_COMMAND );
117: break;
118: }
119: marbuf_send_message( &reply, com );
120:
121: error0: marbuf_final( &request );
122: marbuf_final( &reply );
123: close( com );
124: return;
125:
126: error1: marbuf_marshal_int( &reply, HISCORE_PROTO_MARSHAL_ERROR );
127: marbuf_send_message( &reply, com );
128: goto error0;
129: }
130:
marbuf_receive_message() で、要求メッセージを受信する。
cmd にコマンドに(整数型)を1つ取出す。
cmd が PUT_SCORE の場合、
cmd が GET_HISCORE の場合、
hiscore_records[]のi番目の要素を応答メッ
セージに加える。
hiscore_records[]の
i番目の要素のスコアを、応答メッセージに加える。
hiscore_records[]の
i番目の要素の名前をを、応答メッセージに加える。
131: static void print_my_host_port( int portno ) {
...
138: static int insert_score( score_record_t records[], int len, int nelement,
139: int score, char *user ) {
...
138: static int insert_score( score_record_t records[], int len, int nelement,
139: int score, char *user ) {
...
print_my_host_port()は、自分自身のホスト名と通信ポート番号を表示する。
insert_score() と find_posision() は、
集中のプログラム
と同じ。
167: /* Coins System Program */
170: void tcp_peeraddr_print( int com ) {
...
183: void sockaddr_print( struct sockaddr *addrp, socklen_t addr_len ) {
...
192: int tcp_acc_port( int portno ) {
...
...
13: struct marbuf {
14: uint32_t mb_bytes;
15: char *mb_current;
16: char *mb_buf;
17: size_t mb_buflen;
18: };
19: typedef struct marbuf marbuf_t;
...
...
15: int marbuf_init( marbuf_t *mb, size_t buflen ) {
16: if( (mb->mb_buf = malloc(buflen)) == NULL ) {
17: return( 0 );
18: }
19: mb->mb_buflen = buflen;
20: mb->mb_bytes = 0;
21: mb->mb_current = mb->mb_buf;
22: }
...
24: void marbuf_final( marbuf_t *mb ) {
...
32: int marbuf_receive_message( marbuf_t *mb, int socket ) {
33: uint32_t msglen, msglen_net ;
...
52: int marbuf_send_message( marbuf_t *mb, int socket ) {
53: uint32_t msglen, msglen_net ;
54: msglen = mb->mb_bytes;
55: msglen_net = htonl(msglen);
56: if( write(socket,&msglen_net,sizeof(msglen_net)) != sizeof(msglen_net) ) {
57: perror("write");
58: return( -1 );
59: }
60: if( write(socket,mb->mb_buf,msglen) != msglen ) {
61: perror("read");
62: return( -1 );
63: }
64: mb->mb_bytes = 0;
65: mb->mb_current = mb->mb_buf;
66: return( msglen );
67: }
68:
69: int marbuf_marshal_int( marbuf_t *mb, int data ) {
70: uint32_t data_net ;
71: if( mb->mb_bytes + sizeof(data_net) > mb->mb_buflen )
72: return( 0 );
73: data_net = htonl( data );
74: memcpy( mb->mb_current, &data_net, sizeof(data_net) );
75: mb->mb_current += sizeof(data_net);
76: mb->mb_bytes += sizeof(data_net);
77: return( 1 );
78: }
79:
80: int marbuf_unmarshal_int( marbuf_t *mb, int *datap ) {
81: uint32_t data_net ;
82: if( mb->mb_bytes + sizeof(data_net) > mb->mb_buflen )
83: return( 0 );
84: memcpy( &data_net, mb->mb_current, sizeof(data_net) );
85: *datap = ntohl( data_net );
86: mb->mb_current += sizeof(data_net);
87: mb->mb_bytes += sizeof(data_net);
88: return( 1 );
89: }
90:
91: int marbuf_marshal_byte_array( marbuf_t *mb, char data[], int data_len ) {
92: if( mb->mb_bytes + data_len > mb->mb_buflen )
93: return( 0 );
94: memcpy( mb->mb_current, data, data_len );
95: mb->mb_current += data_len;
96: mb->mb_bytes += data_len;
97: return( 1 );
98: }
99:
100: int marbuf_unmarshal_byte_array( marbuf_t *mb, char data[], int data_len ) {
101: if( mb->mb_bytes + data_len > mb->mb_buflen )
102: return( 0 );
103: memcpy( data, mb->mb_current, data_len );
104: mb->mb_current += data_len;
105: mb->mb_bytes += data_len;
106: return( 1 );
107: }
[Makefile]