参考資料

目的
„
ネットワークプログラミング: UDP
„
TCP/IPの基礎の理解
ソケットプログラミングの基礎の理解
„
CS-24 太田 能
„
どうやってプロセス間通信を実現するのか?
コネクションレスレス型ソケットプログラミングの理解
„
注)コネクション型ソケットプログラミングは2で学習
ネットワークの構成要素
„
„
„
ホスト
ルータ
リンク:LAN/MAN/WAN
TCP/IPの基礎
LAN
ルータ
LAN/MAN/WAN
LAN
LAN
ホスト
TCP/IPプロトコルスタック
IPC (Inter Process Communication)
„
„
受信ホストまでデータが届く
特定のプロセスにデータ渡される
プロセス
„
プロセス
„
„
„
„
プロトコル:規則,手順,規格
IP層:データをホストまで届ける機能
TCP/UDP層:データをプロセスまで届ける機能
ホストインタフェース識別:IPアドレス
プロセス識別:ポート番号
プロセス
プロセス
ルータ
LAN
ホスト
アプリケーション層
各種アプリケーション プロセス
プロセス
プロセス
プロセス
プロセス
プロセス
プロセス
プロセス
LAN/MAN/WAN
LAN
ホスト
アプリケーション層
プロセス間通信
LAN
ホスト
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
エンドホスト間転送
隣接ホスト間通信
TCP
UDP
IP
LAN/WAN
ルータ
IP
TCP
UDP
IP
LAN/WAN
1
クライアント・サーバモデル
ソケット・ポート番号・IPアドレスの関係
送信ホスト
受信ホスト
アプリケーション層
プロセス
アプリケーション層
プロセス
ソケット
6
ポート
1032
TCP
UDP
ソケット
4
ポート
25
ソケット記述子:プロセス側の通信端点識別子
ポート番号:トランスポート層側の通信端点識別子
IPアドレス:ホストのインタフェース識別子
プロセスはソケットに対し読み書きすることで通信を実現
IPアドレス
ルータ
IP
IP
192.168.1.2
192.168.1.1 192.168.5.1
LAN/MAN/WAN
192.168.1.0
TCP
UDP
IP
192.168.5.2
LAN/MAN/WAN
192.168.5.1
送信ホスト内でのメッセージの流れ
送信ホスト
プロセスはソケットにメッセージを書込む
アプリケーション層
プロセス
メッセージ
ソケット
6
送信元ポート
ポート
宛先ポート
1032
セグメント
送信元IPアドレス
TCP
1032;25
宛先IPアドレス
UDP
ルータ
IPデータグラム
192.168.1.2;192.168.5.2
IP
IP
192.168.1.2
192.168.1.1 192.168.5.1
LAN/MAN/WAN
192.168.1.0
ソケット
6
ポート
1032
TCP
UDP
IP
192.168.1.2
プロセス
プロセス
リクエスト
①サーバのIPアドレスとポート番号は既知でなければならない
⇒サーバのポート番号を事前に決め,クライアントに知らせておく必要有
レスポンス
②リクエストからクライアントのIPアドレスとポート番号は分かる
⇒クライアントのポート番号はシステムが適当に決めても可
ソケット
ソケット
4
②自動割当の場合が多い
6
ポート
ポート
①明示的割当必須
25
1032
TCP
実際のデータの流れ
TCP
UDP
UDP
ルータ
IP
IP
IP
LAN/MAN/WAN
LAN/MAN/WAN
ルータ内でのメッセージの流れ
受信ホスト
アプリケーション層
プロセス
アプリケーション層
プロセス
アプリケーション層
プロセス
ソケット
4
ポート
25
ソケット
4
ポート
ルータは経路制御により適切な経路にフォワード 25
ソケット
6
ポート
1032
TCP
UDP
TCP
UDP
IP
192.168.5.2
IP
192.168.1.2
受信ホスト
アプリケーション層
プロセス
メッセージ
ソケット
4
ポート
25
セグメント
TCP
1032;25
UDP
ルータ
IPデータグラム
192.168.1.2;192.168.5.2
IP
IP
192.168.5.2
192.168.1.1 192.168.5.1
プロセスはソケットからメッセージを読込む
LAN/MAN/WAN
192.168.1.0
サーバ
アプリケーション層
送信ホスト
受信ホスト内でのメッセージの流れ
アプリケーション層
プロセス
クライアント:サービスを受ける側
サーバ
:サービスを提供する側
受信ホスト
LAN/MAN/WAN
192.168.5.1
送信ホスト
クライアント
アプリケーション層
LAN/MAN/WAN
192.168.5.1
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
TCP
IPデータグラム
UDP
192.168.1.2;192.168.5.2
ルータ
IP
192.168.1.1 192.168.5.1
LAN/MAN/WAN
192.168.1.0
IP
192.168.5.2
LAN/MAN/WAN
192.168.5.1
TCPセグメントフォーマット
2Bytes
送信元ポート
宛先ポート
シーケンス番号
応答確認番号
u a p r s f
r
c
s s y i
ヘッダ長 予約
ウィンドウ
g k h t n n
チェックサム
緊急ポインタ
オプション,パッディング
ヘッダ メッセージデータ
可変長
2
UDPデータグラムフォーマット
ポート番号 (1/2)
„
目的
„
長さ
プロセスを識別するために使用
„
2Bytes
送信元ポート
セグメント長
ヘッダ
宛先ポート
チェックサム
メッセージデータ
可変長
ポート番号 (2/2)
„
„
„
ポート番号
ウェルノウン (Well-known) ポート
256〜1023
予約済み(スーパーユーザプロセスが使用)
1024〜5000
自動割当範囲(パッシブオープン時に割当)
5001〜65535 ユーザが自由に利用可能な範囲
IP datagram(v4) のフォーマット
20-65535bytes
20-60bytes
有名なプロセスが使用
例)ftp = 21, telnet = 25
プロセス名との対応
„
„
/etc/services の参照
getservbyname() により可能
途 用
0〜255
ウェルノウンポート
„
2バイト (0〜65535)
„
ヘッダ
バージョン
4bits
ヘッダ長
4bits
データ
Type of Service
4bits
Time To Live:8bits
Total length: 16bits
Flags
3bits
Identification:16bits
Protocol:8bits
Fragmentation offset:13bits
Header checksum:16bits
送信元 IP アドレス: 32bits
目的 IP アドレス: 32bits
オプション
IPアドレス
„
目的
„
„
ホスト・ルータのインタフェース識別
論理アドレス
„
„
„
長さ:4バイト(Ver.4) [16バイト(Ver.6)]
ビット表現:10010110 00111011 00100110 11000101
ドット表現:150.59.38.197
トランスポートプロトコル
„
„
„
„
DNS (Domain Name Service) サーバへの問合せ
/etc/hosts の参照により解決
getservbyname()関数から名前解決
„
TCP(Transmission Control Protocol)
コネクション型
バイトストリーム型
UDP(User Datagram Protocol)
„
„
コネクションレス型
非バイトストリーム型
FQDN表現:tama.is.tokushima-u.ac.jp
„ Fully Qualified Domain Name
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
3
TCPによるコネクション通信の実現
送信ホスト
アプリケーション層
プロセス
TCP
„
コネクション型
信頼性の高いエンド間通信を実現
„ IP層における低信頼性をカバー
„
„
„
オーバヘッド大⇒リアルタイム通信には不適
受信ホスト
アプリケーション層
①パッシブオープン(サーバ)
③データ送受信用ソケット
受付ソケットの生成
②アクティブオープン(クライアント)
メッセージ
プロセス
①受付用ソケット メッセージ
②自動割当 コネクション確立要求
ポート番号はTCPが自動割当
ソケット ソケット
ソケット
③コネクション確立応答(サーバ)
5
4
6
メッセージ送受信用ソケット生成
ポート
ポート
④データ転送(クライアント・サーバ)
25
1032
メッセージ送受信用ソケットを利用
スリーウェイハンドシェイク
s;1032;25 ②
バイトストリーム型
„
③ 1032;25;s,a
受信ホストでメッセージの境界が見えない
1032;25 ④
TCP
IP
TCPによる高信頼通信の実現
受信ホスト
時間 ルータ
LAN/MAN/WAN
IP
TCP
時間
IP
LAN/MAN/WAN
TCPによるバイトストリームの実現
アプリケーション層
損失メッセージを補償する
プロセス
ab cd
ef
ab
ソケット
信頼性高い
6
処理が重く低速
ポート fe 1032;25
1032
誤り制御・順序制御
dc 1032;25
アプリケーション層
プロセス
ef
cd
ソケット
5
ポート
ba 1032;25
25
dc 1032;25
受信ホスト
送信ホスト:メッセージを分けて送信
アプリケーション層 受信ホスト:受信メッセージをまとめて読出し アプリケーション層
プロセス
プロセス
ab cd
abcd
ソケット
ソケット
5
6
受信側でメッセージの境界が見えない
ポート
ポート
25
1032
dc 1032;25
ba 1032;25
1032;25
TCP ba UDP
fe 1032;25
UDP
TCP
1032;25
TCP ba UDP
送信ホスト
ba 1032;25 192.168.1.2;192.168.5.2
IP
IP
IP
dc 1032;25メッセージ損失
192.168.1.2;192.168.5.2
②損失メッセージの再送
192.168.5.2
192.168.1.2
fe 1032;25 192.168.1.2;192.168.5.2
LAN/MAN/WAN
LAN/MAN/WAN
192.168.1.0
192.168.5.1
①再送要求
UDP
„
コネクションレス型
„
コネクション設定不要
„
„
低信頼性
„
„
オーバヘッド小
⇒管理アプリケーション,リアルタイム通信に適
必要ならば上位レイヤで保証
非バイトストリーム型
„
受信ホストでメッセージの境界が見える
送信ホスト
IP
192.168.1.2
dc 1032;25
UDP
TCP
ルータ
IP
192.168.1.1 192.168.5.1
LAN/MAN/WAN
192.168.1.0
LAN/MAN/WAN
192.168.5.1
UDPによる非バイトストリームの実現
受信ホスト
送信ホスト:メッセージを分けて送信
アプリケーション層 受信ホスト:受信メッセージを分けて読出し アプリケーション層
プロセス
プロセス
ab cd
ab cd
ソケット
ソケット
4
6
受信側でメッセージの境界が見える
ポート
ポート
13
1032
dc 1032;13
ba 1032;13
送信ホスト
1032;13
TCP ba UDP
IP
192.168.1.2
dc 1032;13
UDP
TCP
ルータ
IP
192.168.1.1 192.168.5.1
LAN/MAN/WAN
192.168.1.0
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
IP
192.168.5.2
IP
192.168.5.2
LAN/MAN/WAN
192.168.5.1
4
UDPによるコネクションレス通信の実現
受信ホスト
送信ホスト
アプリケーション層
プロセス
cd
ef
ソケット
4
ba 1032;13 ポート
13
dc 1032;13
アプリケーション層
損失メッセージを補償しない
プロセス
ab cd
ef
ab
ソケット
信頼性低い
6
処理が軽く高速
ポート fe 1032;13
1032
メッセージ損失検知不可能
dc 1032;13
そのまま上位層に渡す
1032;13
TCP ba UDP
×
ソケットプログラミングの基礎
×
fe 1032;13
UDP
TCP
ba 1032;13 192.168.1.2;192.168.5.2
IP
IP
dc 1032;13 192.168.1.2;192.168.5.2
メッセージ損失
192.168.5.2
fe 1032;13 192.168.1.2;192.168.5.2
LAN/MAN/WAN
LAN/MAN/WAN
192.168.1.0
192.168.5.1
IP
API(Application Programming Interface)
„
カーネルに実装された機能へのインタフェース
„
„
関数やシステムコールにより提供
TCP/IP利用の場合⇒ソケット関数,TLI関数など
アプリケーション層
プロセス
プロセス
プロセス
プロセス
プロセス
プロセス
データ転送
ソケット関数/TLI関数
TCP
ソケットシステムコール一覧
機能
ソケット作成
ソケットに名前設定
接続受付準備
接続要求
接続受付
UDP
ソケットのクローズ
IP
その他
LAN/WAN
gethostbyname関数(1/3)[pp.120-121,124]
ネットワークバイトオーダー
„
ホストにより複数バイトデータの内部表現異なる
„
例) 3000 = 0x0bb8 (2バイトデータ)
リトルエンディアン方式
ビッグエンディアン方式
(インテル80x86等のCPU)
(モトローラ680x0等のCPU)
アドレス
„
b8
0b
n
n+1
アドレス
関数名
socket
bind
listen
connect
accept
read, write, recv, send
recvfrom, sendto
shutdown, close
ioctrl, socketpair, setsocketopt,
getsockopt, getsockname,
getpeername
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
0b
b8
struct
n
n+1
戻り値 成功時…ホスト情報を格納するhostent
構造体へのポインタ
エラー…−1
char *name; ホスト名が格納されている文字列への
ポインタ
通信の際のデータの並びを統一する必要あり
TCP/IPのプロトコルヘッダはビッグエンディアンで処理
htonl();整数(long)をホスト形式からネットワーク形式に変換
„ htons();整数(short)
〃
〃
〃
など(pp.114-115)
„
„
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
hostent*
gethostbyname(char *name);
5
gethostbyname関数(2/3)[pp.120-121,124]
struct
char
char
int
int
char
}
#define
hostent{
*h_name; /* ホストの正式名称 */
**h_aliases; /* 別名リスト */
h_addrtype; /* アドレスタイプ(AF_INET)*/
h_length; /*アドレス長(v.4では4バイト)*/
**h_addr_list; /* アドレスのリスト */
gethostbyname関数(3/3)[pp.120-121,124]
shost = gethostbyname(”tama.is.tokushima-u.ac.jp”);
ホストの正式名称
tama.is.tokushima-u.ac.jp
short = ・
h_name=・
h_aliases=・
ホストの別名リスト
もしあれば
h_addrtype =
構造体の在処
(アドレス)を格納
したポインタ変数
AF_INET
h_length = 4
h_addr_list=・
:
h_addr (=h_addr_list[0])
アドレスリスト
150 59 38 197
もしあれば
h_addr h_addr_list[0]
/* アドレス(下位互換性保持のため) */
:
tama.is.tokushima-u.ac.jpの調査結果を格納した構造体
UDPソケットプログラミングの流れ
クライアント
サーバ
アプリケーション層
両方とも同様な流れ
アプリケーション層
サーバのポート番号は
プロセス
プロセス
明示的割付必要
準備
準備
①socket(); ソケット生成
①socket();
②bind();
情報割付
②bind();
送受信(③④繰返し)
送受信(③④繰返し)
UDPプログラミング
③sendto(); 相手(IP+ポート)へ送信
③recvfrom();
④recvfrom();相手(IP+ポート)から受信 ④sendto();
終了
終了
⑤close(); ソケットクローズ
⑤close();
sockaddr_in構造体
ソケット
ソケット
①⑤ アドレスファミリー
自動割当可 6
5 明示的割付
ポート番号
ポート ②
ポート
1032
13
UDP
UDP
IPアドレス
IP
socket 関数 (1/4)[pp.110-111]
機能:ソケットを作成する
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
戻り値 成功時…ソケット記述子,エラー…−1
未使用
LAN/MAN/WAN
socket 関数 (2/4)[pp.110-111]
„
ドメイン
„
„
„
„
int type;
コネクション型かコネクションレス型を指定
int protocol; TCPあるいはUDPを指定
„
SOCK_STREAM…コネクション型
SOCK_DGRAM…コネクションレス型
プロトコル
„
„
„
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
AF_INET…INETドメイン(インターネットドメイン)ネットワーク越し
AF_UNIX…UNIXドメイン(同一ホスト内プロセス間通信)
タイプ
„
int domain; 通信領域を指定
IP
IPPROTO_TCP…TCP/IP
IPPROTO_UDP…UDP/IP
0…ドメインとタイプから適切なものを自動選択
6
socket 関数 (3/4)[pp.110-111]
アプリケーション層 クライアント
サーバ
socket 関数 (4/4)[pp.110-111]
アプリケーション層
<サーバ, クライアント(UDP/IP)での使用例>
int soft;
sofd = socket( AF_INET, SOCK_DGRAM, 0);
if ( sofd < 0 ){ エラー処理; }
プロセス
プロセス
sofd には 6 が代入される.
準備
準備
①socket(); 0);
①sofd = socket(AF_INET, SOCK_DGRAM,
②bind();
②bind();
ネットワーク越し,コネクションレス通信,UDP
送受信(③④繰返し)
送受信(③④繰返し)
③recvfrom();
③sendto();
UDP/IP上で利用可能な,識別
④sendto();
④recvfrom();
子6番のソケットが生成されている.
終了
終了
⑤close();
⑤close();
ソケット
ソケット
5
6
この状態では,ポート番号等との
関連付けはなされていない.
ポート
ポート
13
UDP
UDP
IP
LAN/MAN/WAN
IP
bind 関数 (1/7)[pp.112-116]
bind 関数 (2/7)[pp.112-116]
機能:ソケットに名前を付ける(情報割付)
/* INETドメインで利用するアドレス構造体 */
#include <sys/types.h>
struct
sockaddr_in{
#include <sys/socket.h>
short
int bind(int s, struct sockaddr* name, int namelen);
u_short sin_port;
戻り値 成功時…0,エラー…−1
int s; ソケット記述子
struct sockaddr* name; 対応アドレス構造体へのポインタ
int namelen; アドレス構造体のサイズ
sin_family; /* ドメイン(常にAF_INET) */
/* ポート番号 */
struct
in_addr sin_addr;/* IPアドレス格納構造体 */
char
sin_zero[8]; /* パディング */
};
struct
u_long
in_addr{
s_addr;
/* IPアドレス */
}
bind 関数 (3/7)[pp.112-116]
bind 関数 (4/7)[pp.112-116]
アプリケーション層 クライアント
サーバ
プロセス
/* クライアントにおけるアドレス構造体設定例 */
struct
sockaddr_in
cl_addr;
bzero((char*)&cl_addr, sizeof(cl_addr)); /*初期化*/
cl_addr.sin_family = AF_INET;
/*ドメイン*/
cl_addr.sin_port = htons( 0 ); /* システム自動割当 */
cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* INADDR_ANY = 0 インタフェースの制限なし */
準備
準備
①sofd = socket(AF_INET,SOCK_DGRAM,0);
①socket();
②bind(sofd,(struct sockaddr*)&cl_addr,sizeof(cl_addr));
②bind();
送受信(③④繰返し)
送受信(③④繰返し)
アドレス構造体 cl_addr
③sendto();
③recvfrom();
の在処(アドレス)を渡す
④sendto();
④recvfrom();
終了
終了
⑤close();
⑤close();
struct sockaddr_in
cl_addr;
ソケット
ソケット
アドレスファミリー = AF_INET (ドメイン)
自動割当
6
5
ポート番号 = 0 (ワイルドカード⇒システム自動割当)
ポート
ポート
1032
IPアドレス = INADDR_ANY(0)(インタフェース制限なし)
13
UDP
UDP
IP
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
アプリケーション層
プロセス
未使用
LAN/MAN/WAN
IP
7
bind 関数 (5/7)[pp.112-116]
bind 関数 (6/7)[pp.112-116]
サーバ
アプリケーション層
プロセス
/* サーバにおけるアドレス構造体設定例 */
struct
sockaddr_in
sv_addr;
bzero((char*)&sv_addr, sizeof(sv_addr)); /*初期化*/
sv_addr.sin_family = AF_INET;
/*ドメイン*/
sv_addr.sin_port = htons( 13 );
/* 明示的割当 */
sv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* INADDR_ANY = 0 インタフェースの制限なし */
準備
①sofd = socket(AF_INET,SOCK_DGRAM,0);
②bind(sofd,(struct sockaddr*)&sv_addr,sizeof(sv_addr));
送受信(③④繰返し)
アドレス構造体 sv_addr
③ recvfrom();
の在処(アドレス)を渡す
④ sendto();
終了
⑤close();
ソケット
明示的割当 5
ポート
13
UDP
struct sockaddr_in sv_addr;
アドレスファミリー = AF_INET (ドメイン)
ポート番号 = 13 (明示的割当)
IPアドレス=INADDR_ANY(=0:インタフェース制限なし)
未使用
IP
MAN/WAN
bind 関数 (7/7)[pp.112-116]
メッセージの送受信
<クライアント(UDP/IP)での使用例>
structsockaddr_in
cl_addr;
cl_addr の設定;
bind(sofd,(struct sockaddr*)&cl_addr,sizeof(cl_addr));
/*本来なら戻り値の正負を判断し,エラー処理を行う*/
„
„
„
„
<サーバ(UDP/IP)での使用例>
„
structsockaddr_in
sv_addr;
sv_addr の設定;
bind(sofd,(struct sockaddr*)&sv_addr,sizeof(sv_addr));
/*本来なら戻り値の正負を判断し,エラー処理を行う*/
int s; ソケット記述子
char *buf; 送信メッセージのバッファアドレス
int lens; 送信メッセージのサイズ
int flag; 送信メッセージのフラグ(通常0,p.146参照)
struct sockaddr* to;相手先のアドレス構造体へのポインタ
int tolen; アドレス構造体のサイズ
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
send………コネクション型のみで利用可能
sendto……双方で利用可能
sendmsg…双方で利用可能
受信
„
„
„
sendto 関数 (1/3)[pp.116-119]
機能:メッセージをソケットに送信する
#include <sys/types.h>
#include <sys/socket.h>
int sendto(int s, char *buf, int lens, int flag,
struct sockaddr *to, int tolen);
戻り値 成功時…送信されたバイト数,エラー…−1
送信
recv………コネクション型のみで利用可能
recvfrom…双方で利用可能
recvmsg …双方で利用可能
sendto 関数 (2/3)[pp.116-119]
アプリケーション層 クライアント
準備 プロセス
サーバ
アプリケーション層
①sofd = socket(AF_INET,SOCK_DGRAM,0);
②bind(sofd,(struct sockaddr*)&cl_addr,sizeof(cl_addr));
送受信(③④繰返し)
smsg(送信メッセージ)
③sendto(sofd, smsg, nbyte, 0,
(struct sockaddr*)&sv_addr, svadlen);
④recvfrom();
終了
⑤close();
ソケット
6
ポート
1032
UDP
IP
在処(アドレス)を渡す
gethostbyname()で調べる
サーバ情報のアドレス構造体
struct sockaddr_in sv_addr;
192.168.1.2
アドレスファミリー = AF_INET
ポート番号 =13
IPアドレス =192.168.5.2
未使用
LAN/MAN/WAN
ソケット
5
ポート
13
192.168.5.2
UDP
IP
8
gethostbyname関数(3/3)[pp.120-121,124]
shost = gethostbyname(”tama.is.tokushima-u.ac.jp”);
struct hostent *shost;
shost = ・
h_name=・
h_aliases=・
h_addrtype =
AF_INET
h_length = 4
h_addr_list=・
h_addr (=h_addr_list[0])
アドレスリスト
150 59 38 197
:
1バイトづつコピー
struct sockaddr_in sv_addr;
sin_family = AF_INET
sin_port = 13
#define PORT_NO 13
sin_addr
bzero((char*)sv_addr,sizeof(sv_addr));
s_addr=150.59.38.197
sv_addr.sin_family = AF_INET; 未使用
sv_addr.sin_port = htons(PORT_NO);
bcopy(short->h_addr, (char*)&sv_addr.sin_addr.s_addr,
p.113表4.2参照
short->h_length );
recvfrom 関数 (1/2)[pp.116-119]
機能:メッセージをソケットから受信する
#include <sys/types.h>
#include <sys/socket.h>
int
rcvfrom(int s, char *buf, int lens, int flag,
struct sockaddr *from, int *fromlen);
戻り値 成功時…受信したバイト数,エラー…−1
int s; ソケット記述子
char *buf; 受信メッセージのバッファアドレス
int lens; 受信メッセージのサイズ
int flag; 受信メッセージのフラグ(通常0,p.147参照)
struct sockaddr* from;送信元のアドレス構造体へのポインタ
int *fromlen; アドレス構造体のサイズへのポインタ
recvfrom 関数 (2/2)[pp.116-119]
アプリケーション層 クライアント
準備 プロセス
サーバ
アプリケーション層
①sofd = socket(AF_INET,SOCK_DGRAM,0);
②bind(sofd,(struct sockaddr*)&cl_addr,sizeof(cl_addr));
送受信(③④繰返し)
rmsg(受信メッセージが書き込まれる)
③sendto(sofd, smsg, nbyte, 0,
(struct sockaddr*)&sv_addr, svadlen);
④recvfrom(sofd, rmsg, BUFFMAX, 0,
(struct sockaddr*)&sv_addr,&cladlen);
ソケット
ソケット
終了
サーバ情報のアドレス構造体
6
struct sockaddr_in sv_addr; 5
⑤close();
ポート
アドレスファミリー = AF_INET
ポート
送信元情報(誰
1032
13
UDP
UDP
ポート番号 =13
が送ってきたの
IPアドレス =192.168.5.2
か)がアドレス構造
IP 192.168.1.2
192.168.5.2 IP
体に記入される
LAN/MAN/WAN
未使用
close 関数 (1/2)[pp.95-96]
機能:ソケットを閉じる
#include <unistd.h>
int close(int d);
戻り値 成功時…0,エラー…-1
int
s; ファイル(ソケット)記述子
close 関数 (2/2)[pp.95-96]
アプリケーション層 クライアント
サーバ
アプリケーション層
準備 プロセス
プロセス
①sofd = socket(AF_INET,SOCK_DGRAM,0);
準備
②bind(sofd,(struct sockaddr*)&cl_addr,sizeof(cl_addr));
①socket();
送受信(③④繰返し)
②bind();
③sendto(sofd, smsg, nbyte, 0,
送受信(③④繰返し)
(struct sockaddr*)&sv_addr, svadlen);
③recvfrom();
④recvfrom(sofd, rmsg, BUFFMAX, 0,
④sendto();
(struct sockaddr*)&sv_addr,&svadlen);
終了
終了
⑤close(sofd);
⑤close();
ソケット
ソケットを閉じる
ソケット
6
5
ポート
ポート
1032
13
UDP
UDP
IP
192.168.1.2
LAN/MAN/WAN
その他
IP
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
9
select 関数 (1/7) [pp.168-170]
select 関数 (2/7) [pp.168-170]
送受信関数・入出力関数は通常ブロックされる
複数の送受信・入出力がスムーズに行えない
select 関数の使用
サーバ
アプリケーション層 クライアント
アプリケーション層
int fn;
fn = fileno(stdin); /*fn には 0 が代入される*/
read(fn, msg, MAXMSG);
キーボード入力が終わるまでソケット
recvfrom(sofd, 略…);
ソケット
6
ポート
UDP 1032
IP
sofdからのメッセージ受信ができない
ファイル
(整数)記述子
0
ソケット
5
ポート
13
UDP
LAN/MAN/WAN
IP
select 関数 (3/7) [pp.168-170]
int nfsd; ビットマスク中の使用ビット幅
fd_set* rfsd; 読取可能なファイル記述子を監視する
ためのビットマスクへのポインタ
fd_set* wfsd; 書取可能なファイル記述子を監視する
ためのビットマスクへのポインタ
fd_set* efsd; 例外状態のファイル記述子を監視する
ためのビットマスクへのポインタ
select 関数 (5/7) [pp.168-170]
ビットマスクのビット操作マクロ
int fd;
fd_set fdset;
FD_ZERO(&fdset);ビットマスクを0クリア
FD_SET(fd, &fdset);ファイル(整数)記述子fdを
ビットマスク fdset にセットする
FD_CLR(fd, &fdset);ファイル(整数)記述子 fd を
ビットマスク fdset から除く
FD_ISSET(fd, &fdset); ファイル(整数)記述子 fd が
ビットマスク fdset に含まれるなら
1を,含まれないなら0を返す
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
機能 入出力の多重待ち
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
int select(int nfsd, fd_set* rfsd, fdset* wfsd,
fdset* efsd, struct* timeout);
戻り値 成功時…ビットマスク中に含まれるI/O可能な
ファイル記述子
タイムアウト…0
エラー…−1
select 関数 (4/7) [pp.168-170]
struct timeval* timeout;
timeval構造体へのポインタ
NULLのとき:
selectはブロック
NULL以外のとき:
select が完了するまでの最大待ち
時間を書いたtimeval構造体のアド
レスを指定
select 関数 (6/7) [pp.168-170]
ファイル記述子・ファイル整数記述子変換関数
#include <stdio.h>
int fileno(FILE *stream);
戻り値 ファイル整数記述子
FILE *stream; ファイル記述子
例)
fileno(stdin) → 0 fget(msg,MAXMSG,stdin);
等価
fileno(stdout) → 1
read(0,msg,MAXMSG);
fileno(stderr) → 2
10
select 関数 (7/7) [pp.168-170]
アプリケーション層
ビットマスクrfsd_org
int
fin, max_rfd;
fd_set rfsd, rfsd_org; 63 … 7 6 5 4 3 2 1 0
0 … 0 1 0 0 0 0 0 1
fin = fileno(stdin);
FD_ZERO(&rfsd_org);
使用ビット幅 = 7
FD_SET(fin, &rfsd_org); FD_SET(sofd, &rfsd_org);
select後
max_rfd = (fin<sofd) ? sofd: fin;
読出し可能
課題
63 … 7 6 5 4 3 2 1 0
rfsd
while(1){
rfsd = rfsd_org; 0 … 0 1 0 0 0 0 0 0
select( max_rfd + 1, &rfsd, NULL, NULL, NULL);
if(FD_ISSET(fin, &rfsd)) read(fin, msg, MAXMSG);
if(FD_ISSET(sofd, &rfsd)) recvfrom(sofd, 略…);
}
UDP
ファイル
(整数)記述子
0
ソケット
6
ジャンケンゲームの概要
目的
„
TCP/IP プロトコルの仕組みの理解
UDPプログラミングの理解
„
„
„
„
サーバ・クライアント型プログラム
トランスポートプロトコルはUDP
同時ゲーム参加クライアント数:2台まで
„
3台以上のゲーム参加は拒絶
ジャンケンゲームサーバの作成
メッセージシーケンス概要(1/2)
クライアント1
サーバ
connect
message
message送受信
close
message
connect
message
メッセージシーケンス概要(2/2)
クライアント2
message送受信
close
message
close
message
any message
他のクライアント
途中参加のクライアント
はいかなるメッセージを
送っても close メッセージ
が返るのみで無視
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
クライアント1
connect
message
message送受信
reset message
close
message
サーバ
connect
message
message送受信
クライアント2
close
message
両方(クライアント2にも)のクライアントに
close メッセージを送信し,強制リセット
11
クライアントの実行例
サーバの実行例
使用方法: client [server_name] [server_port]
強制終了:reset+改行をコマンドライン入力
サーバの内部状態遷移
„
使用方法: server [server_port]
終了方法: quit+改行をコマンドライン入力
サーバの内部状態遷移図
①クライアントからconnect
コマンドを以外を受信
4状態間を遷移
„
„
„
„
NON_PERSON: ゲームに誰も参加していない
ONE_PERSON: 1人ゲームに参加
TWO_PERSONS: 2人ゲームに参加
FIRST_TOSS: 1人が既にグー,チョキ,パーの
どれかを出している
調査課題
„
„
UDPとTCPの違いをA4用紙1枚程度で述べよ.
プログラム課題
„
„
„
ジャンケンゲームサーバを完成させよ.
サーバの状態遷移図を完成させ,この図を使って
サーバプログラムの動作を詳細に解説せよ.
サーバプログラムの各行にコメントを加え,レポート
の付録として添付せよ.
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
NO_PERSON
開始
②クライアントからconnect
メッセージを受信
クライアント1として保存
③コマンドラインから
quit コマンドを入力 ④クライアント1からconnect ONE_PERSON
コマンドを受信
⑤クライアント1以外からconnect
終了
コマンド以外を受信
①:connect message を送信 ⑦コマンドラインから
⑥クライアント1
するよう通知
quit コマンドを入力 以外から
②…
connectコマン
終了
③…
ドを受信
レポート課題(1/2)
„
⑦クライアント1から reset
コマンドを受信
レポート課題(2/2)
„
プログラム課題(つづき)
„
„
プログラムをメールに添付し,太田まで提出せよ.
添付にあたっては次の指示を守ること.
Makefile も含めすべてのソースファイル(*.c, *.h)を
tar で圧縮しつつ,ひとつにまとめる.
例) tar cvfz program.tgz *.c *.h Makefile
„ メールアドレス:[email protected]
„ サブジェクト: network programming 1
„
12
利用可能なリソース
„
サンプル・ソース・バイナリの在処
„
http://baltan.is.tokushima-u.ac.jp
/~ohta/lecture/experiment/
/network-programming/index.html
„
プログラム一式
„
„
„
„
„
Makefile
toss_game.h
toss_game.c
client.c
server.c
手を加えてよい
手を加えてよい
手を加えてよい
手を加えてよい
未完成 ⇒ 完成させよ(課題)
ソフトウェア設計及び実験:ネットワークプ
ログラミング1
13