ネットワーク・プログラミング ソケットオプションとスレッド
optValのサイズを格納したint型変数のアドレス 1.1 ソケットオプション optValのサイズを格納したint型変数のアドレス 層(レイヤ) オプション名 値 オプションを読出す int getsockopt(int socket, int level, int optName, void *optVal, unsigned int *optLen) オプションを設定する int setsockopt(int socket, int level, int optName, const void *optVal, unsigned int optLen) ソケット層 optValのデータ型 TCP層 SOL_SOCKETレベル, データ型, 値 SO_BROADCAST, int, 0/1 説明 ブロードキャストを有効にする SO_KEEPALIVE, int, 0/1 キープアライブを有効にする SO_LINGER, linger{}, 時間 close()が確認を待つための遅延時間 SO_RCVBUF, int, バイト数 ソケットの受信バッファサイズ。 SO_RCVLOWAT, int, バイト数 recv()が処理を戻すまでに受信するバイト数の最小値 SO_REUSEADDR, int, 0/1 すでに使用中のアドレス/ポートへのバインドを有効にする SO_SNDLOWAT, int, バイト数 送信パケットのバイト数の最小値 SO_SNDBUF, int, バイト数 ソケットの送信バッファサイズ IPPROTO_TCPレベル, データ型, 値 TCP_MAX, int, バイト数 説明 キープアライブメッセージの間隔 TCP_NODELAY, int, 0/1 Nagleアルゴリズムの禁止 値 IPPROTO_IPレベル, データ型, 値 IP_TTL, int, 0~255 説明 IPパケットのユニキャスト存続時間 IP_MULTICAST_TTL, unsigned char 0~255 IPパケットのマルチキャスト存続時間 IP_MULTICAST_LOOP, int, 0/1 自身がマルチキャストソケットで送信したパケットの受信を有効にする IP_ADD_MEMBERSHIP, ip_mreq{}, グループアドレス 指定したマルチキャストグループのパケットの受信を有効にする IP_DROP_MEMBERSHIP,ip_mreq{}, グループアドレス 指定したマルチキャストグループのパケットの受信を無効にする オプション名
1.2 ノンブロッキングソケット data data/syn ブロック ノンブロック syn syn,ack ack ノンブロッキング 1.2 ノンブロッキングソケット Client Server send() sendto() ノンブロッキング 関数の呼出しをブロックしないように成功/失敗を表す値がすぐに返るようにする。 ソケットのノンブロッキング化 int fcntl(int socket, int command, long argument) command: F_GETFL: フラグを表示 F_SETFL: フラグを設定 argument: フラグ名 O_NONBLOCK: ノンブロックにする ノンブロッキングソケットの動作 connect()以外は、処理を正常に行うか、或いは(処理することがなければ)直ぐにエラーを返す。 connect()では、EINPROGRESS(コネクション確立中)のエラーを返す。 ノンブロッキングの欠点 同じ処理を定期的に何度も試行(ポーリング)しなければならない。 data 成功 recv() recvfrom() accept() ブロック data/syn 成功 recv() ノンブロック 受信が失敗したのではなくて、受信データが無いので直にリターンした エラー EWOULDBLOCK connect() syn エラー EINPROGRESS syn,ack ack
2.スレッド 2.1 スレッドの生成 forkシステムコールの欠点 スレッドを使えば並行して実行するプログラムが容易に書くことが出来る。 2.スレッド 2.1 スレッドの生成 forkシステムコールの欠点 子プロセスが親プロセスの情報を複製するための処理が重い。 親プロセスや他のプロセスとの情報交換にパイプやプロセス間通信を使わなければいけない。 スレッドを使えば並行して実行するプログラムが容易に書くことが出来る。 スレッドを使う場合、main関数が終了すると全てのスレッドが終了する。 プロセスのfork()に対応 pthread_create スレッドを生成する インクルードファイル #include <pthread.h> 書式 int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); 戻値 成功時 0 (スレッド識別子を*threadに設定) 失敗時 0以外の値 *thread スレッド識別子を格納する変数 *attr スレッドの属性、 NULL: デフォルトの属性 *start_routine スレッドが実行する関数 *arg スレッドが実行する関数の引数 start_routineは関数へのポインタ変数 プロセスのwait()に対応 pthread_join スレッドが終了するのを待つ インクルードファイル #include <pthread.h> 書式 int pthread_join(pthread_t th, void **thread_return); 戻値 成功時 0 失敗時 0以外の値 th 終了待ちスレッド thread_return スレッドの戻り値 ポインタ変数のアドレスを保持するポインタ変数
lv2.c 引数で指定した時間の5分前にメッセージ表示 2.2 目覚まし時計プログラム lv2.c 引数で指定した時間の5分前にメッセージ表示 スレッドの場合 プロセスの場合 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { pthread_t thread; void *print_message(void *args); pthread_create(&thread, NULL, print_message, argv[1]); pthread_join(thread,NULL); return EXIT_SUCCESS; } void *print_message(void *args) { int dep_time; dep_time=atoi(args)*60-300; sleep(dep_time); fprintf(stderr, "You have to leave in 5 minutes\n"); return NULL; lv.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> Int main(int argc,char *argv[]) { int dep_time; int st; dep_time=atoi(argv[1])*60-300; if (fork()==0) { //子プロセスの生成 sleep(dep_time); fprintf(stderr,”Leave in 5 min\n”) exit(EXIT_SUCCESS); } wait(&st); return EXIT_SUCCESS; [oida@rpc261 soft2]$ gcc lv.c –o lv [oida@rpc261 soft2]$./lv 30 [oida@rpc261 soft2]$ [oida@rpc261 soft2]$ Leave in 5 min [oida@rpc261 soft2]$ gcc lv2.c -o lv2 -lpthread [oida@rpc261 soft2]$ ./lv2 30 You have to leave in 5 minutes [oida@rpc261 soft2]$ pthreadライブラリが必要
宿題12 (lv2.cを参考にして)スレッドを使って、20秒前と5秒前にメッセージを出すプログラム(hw12.c)。 表紙に氏名と学籍番号を書く 本文にプログラムを書く プログラムの実行結果を書く 実施した内容を説明する文章を書く レポートの締切は次の週の水曜日18:00 main() thread[0] thread[1] pthread_create pthread_create print pthread_join 20秒前 pthread_join print [oida@rpc261 soft2]$ gcc hw12.c -o hw12 -lpthread [oida@rpc261 soft2]$ ./hw12 30 You have to leave in 20 seconds You have to leave in 5 seconds [oida@rpc261 soft2]$ 5秒前 秒単位で指定する。
宿題12 hw12.c thread[0] thread[1] main() #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { pthread_t thread[2]; void *print_message(void *args); void *print_message2(void *args); pthread_create(&thread[0], NULL, print_message, argv[1]); pthread_create(&thread[1], NULL, print_message2, argv[1]); pthread_join(thread[0],NULL); pthread_join(thread[1],NULL); return EXIT_SUCCESS; } void *print_message(void *args) { int dep_time; dep_time=atoi(args)-20; sleep(dep_time); fprintf(stderr, "You have to leave in 20 seconds\n"); return NULL; void *print_message2(void *args) { thread[0] thread[1] main() pthread_create pthread_join print この部分に、5秒前にメッセージ を出す命令文(3行)を書く。
まとめ ソケットオプション ノンブロッキングソケット スレッド 目覚まし時計プログラム