ネットワークプログラミング 第4回

ネットワークプログラミング
第4回
システムコール
低水準入力
ファイルディスクリプタ
ソケット
ライブラリとシステムコール
• ライブラリ
– 便利な関数
– オペレーティングシステムに必ずしも要求を行わない
– ライブラリを利用すると、ユーザが直接オペレーション
システムに要求しなくても勝手にやってくれる。
• システムコール
– オペレーティングシステムにユーザが直接要求を行う
– システムコールの数はあまり多くない
システムコール
• どんなことができる?
–
–
–
–
入出力やファイルシステムへの低水準な操作
プロセスに対するさまざまな制御
ネットワークへの対応
ライブラリでは手のとどかない部分を操作できる。
• 返り値
– システムコールは、エラーが生じると-1を返す
– エラーがない場合は整数値か0を返す
– 予約された外部参照変数 errnoには、どのエラーが発生
したかを示す番号がセットされる(error.h)
低水準入力
• ライブラリを通さず、直接ユーザがファイル
やデバイスの操作を行う
– 読み込み、書き込み、etc …
• UNIXではファイル、デバイス、ネットワーク、
プロセスなどあらゆるものがファイルとして
抽象化されている
– 低水準入力で、ファイルとして抽象化されたあ
らゆる対象を操作できる
ファイルディスクリプタ
• プロセスが外の世界と通信する為のデータの出入り口
• ファイルやデバイスの操作、他プロセスとの通信など、外
の世界とのIO全てがファイルディスクリプタを経由
• プロセスから見ると整数値
ファイル
ファイル
デバイス
0
プロセス
1
2
0:標準入力
1:標準出力
2:標準エラー出力
ファイルディスクリプタの操作
• Open()
– Openシステムコールを使い、ユーザはファイルやデバ
イスをプロセスから利用可能にする。Openは戻り値に
整数値(ファイルディスクリプタを返す)
– Ex. fd = open(“naisho.txt”, O_RDONLY)
/* naisho.txt を読み出し専用で開く */
• Close()
– ファイルディスクリプタのクローズ
– Ex. close(fd) /*fdは過去にopen したファイルディスクリプタ*/
読み書き
• read(int fd, void *buf, size_t nbytes)
– fd からbuf へ nbytes だけ読み込む
– Buf は事前にmallocしておく
– 返り値は、実際に読み出したバイト数
• write(int fd, void *buf, size_t nbytes)
– fd へbuf から nbyteだけ書き込む
– 返り値は、実際に書き込んだバイト数
ソケット(Socket)
•
•
•
プロセス間通信を行う為のデータの出入り口
プロセスからはファイルディスクプリタを用いてアクセス
プロセスにとってはプロセス間通信もファイル入出力も
同じインターフェイス
プロセス
socket
socket
プロセス
ネットワークの話
階層化構造
MACアドレス、IPアドレス
ポート
TCP/UDP
メッセージを伝えるには
• 思ったことを伝えるには
– 言葉や、身振り手振りで伝える
– 何かを媒介して相手に伝える
• なぜ、伝わるか
– 言葉
• 発した言葉、書かれた記事の意味と同じ意味を相手も知っ
ている
– 身振り手振り
• 相手の動作がどんな意味を持つか、コンテクストやコード
から推測
役割分担: 階層モデル
発話者
受話者
意思の伝達
意思の言葉への変換
言語の伝達
空気
物理的な伝達
コンピュータネットワークにおける
階層化モデル
• OSI参照7層モデル
– コンピュータネットワークモデルの基礎
• コンピュータ同士がコミュニケーションする場合も
階層がある。
– 人間の脳⇔脳、口⇔耳と同じ
• 各層は上下の層とだけ関係を持つ
– 脳は口や耳と関係を持つが空気とは直接関係しない
– 自分の一つ上と一つ下以外とは話をしない
OSI参照7層モデル
• コンピュータネットワークのアーキテクチャを論理的に整理
• プロトコル設計の物差し
Application
Application
Presentation
Presentation
Session
Session
Transport
Transport
Network
Network
Datalink
Datalink
Physical
Physical
OSI参照モデルと
インターネットの階層構造の関係
OSI参照7層モデル
インターネットの階層構造
Application
Presentation
Application
Session
Transport
TCP
UDP
Network
IP
Datalink
NIC, データリンクプロトコル
Physical
Physical
インターネットの階層モデル
• IPによってエンドエンドの通信が確立
• TCP/UDPによって通信の性質を選択
– TCPによって信頼性のある通信を行う
– UDPによって信頼性がないが、高速で単純な通信を行う
Application
Application
Application
Application
TCP
TCP
TCP
TCP
IP
IP
IP
IP
Datalink
Datalink
Datalink
Datalink
Physical
Physical
Physical
Physical
各層での識別子
• 各層ごとに識別子が存在する
• 各層は層毎に相手を識別している
Application
TCP
UDP
IP
Network
Interface
Physical
ポート番号
IPアドレス
MACアドレス
MACアドレス
• 通信機器が持つ識別子
–
–
–
–
通信機器ごとにユニークなアドレスを持つ
固定で割り当てられる
IEEEが管理、割り当て
00:90:99:1F:95:E3
• NIC(Network Interface Card)が持っている
IPアドレス
• インターネット上のコンピュータの識別子
–
–
–
–
コミュニケーション相手の場所を指定できる
電話番号や住所に相当
IPv4では32bit、IPv6では128bit
アドレス表記
• IPv4
• IPv6
203.178.143.1 とか
2001:200:0:1000::1 とか
– 識別できるアドレスの数
• IPv4 … 32bit …. 約43億個
• IPv6 … 128bit …. 2^128個
ポート番号
• サービスの識別子(0~65535)
• プロトコルごとに独立したポートを持つ
– Ex. TCPの53番とUDPの53番は別のサービス
• コミュニケーションの相手を指定できる
– 住所(IP address)に対する部屋番号に相当
コーポシュガーの“202号室”
– 電話 … 相手の呼び出し
「“りんご君”をお願いします。」
• IPアドレスとポート番号の組で、コミュニケーショ
ンしたい相手を特定できる
• 誰かが使っているポートは、他のプロセスは使
えない。
Wellknownポート
• 1~1023番
–
–
–
–
–
あらかじめ予約されているポート
Ssh
22番
telnet 23番
dns 53番
http 80番
• /etc/services
telnet で遊ぶ
• telnet 相手先IPアドレス ポート番号
– 相手先の指定したポート番号を使っているア
プリケーション(server)にTCPでコネクションが
張れる。
– SMTPサーバと話してみよう
– WEBサーバと話してみよう
トランスポートプロトコル
• UDP(User Datagram Protocol)
– 信頼性のないデータグラム型通信
– Connectionless
• TCP(Transmission Control Protocol)
– 信頼性のあるストリーム型通信
– Connection Oriented
– Virtual Circuit
UDP (User Datagram Protocol)
• 送信者は、パケットを順に送り出すだけ
• 受信側は、受け取ったパケットを受け取っ
た順に上位層に渡すだけ
– 誤りが見つかっても、途中でパケットが消失し
ても再送信は行わない
– パケットの順序も気にしない
UDPを用いたサービス
• パケット損失率や伝播遅延の変動が少ない
安定した通信路を想定
– NFS, TFTP, SNMP
• 即時性、実時間性重視
– DNS, 音声/動画ストリーミングアプリケーション
TCP
(Transmission Control Protocol)
• アプリケーション間に信頼性のある通信を提供
• IPが提供する通信に信頼性を与える
–
–
–
–
–
コネクション型通信
再送機能
エラー検出とエラー訂正
フロー制御
順序の再構成
TCPを用いたサービス
• データの信頼性を保証したい
– HTTP、FTP、SMTP
– コンピュータ同士が遠く離れていても大丈夫
• データが届く順番を確保したい
– SSH、チャット
クライアント・サーバモデル
• サーバは特定のアドレスとポートで、クライアント
が接続するのを待っている
• クライアントが使うポートは、起動時に割り当てら
れる。
WWW Server
IP address: 133.27.4.212
Port: 80, TCP
Client
133.27.4.212
TCPの80番にアクセス
階層化構造に直してみると。。
www
client
www
server
TCP
telnet
server
#80 #53
#2048
UDP
dns
server
transport
layer
UDP
#23
TCP
IP
network
layer
IP
Ethernet
Datalink/
Physical layer
Ethernet
プログラミング
Socket
Bind
Socketのread/write
イメージを明確にすると…
ソケット
クライアント
プロセス
Port X
ソケット
Port A
サーバ
プロセス
Port B
Port C
ホストA
IP Address: yy.yy.yy.yy
ホストB
IP Address: xx.xx.xx.xx.
socket()システムコール
• int socket(int family, int type, int proto)
– プロセスから利用できるsocketを獲得
– familyにはプロトコルファミリを指定
• AF_INET
• AF_INET6
IPv4プロトコル
IPv6プロトコル
– Typeにはソケットのタイプ(以下のどれか)
• SOCK_STREAM
• SOCK_DGRAM
• SOCK_RAW
ストリームソケット
データグラムソケット
rawソケット
– Protoにはrawソケット以外、通常0
socket()システムコール
• 返り値
– 成功: ソケットディスクリプタが返る
– 失敗: -1が返る
• ソケットディスクリプタはファイルディスクリプタの友達
• 例
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
• 通信に利用するには、各ソケットに宛先IPアドレスや
ポート番号を結びつける必要がある
sockaddr_in構造体
• ソケットの情報を格納
struct sockaddr_in {
u_char sin_len;
u_char sin_family; /* AF_INET,AF_INET6…*/
u_short sin_port; /*相手先ポート番号 16bit */
struct in_addr sin_addr; /*相手先アドレス */
char sin_zero[8];
};
Connect()システムコール
• Int connect(int s, const struct sockaddr *name, socklen_t
namelen);
• 第二引数で指すSockaddr構造体が通信先を特定
• 実際のコードの例
Struct sockaddr_in sin;
Sin.sin_family = AF_INET /*プロトコルファミリー */
sin.sin_addr.s_addr = inet_addr(“203.178.143.1”); /* IPアドレス*/
Sin.sin_port = htons(1234); /* ポート番号 */
Connect(s, (struct sockaddr *)&sin, sizeof(sin));
• 成功なら0, エラーなら-1の返り値
ネットワーク・バイト・オーダ
• Network Byte Order
• CPUアーキテクチャによって、バイトの並びが違う
– 一般にBig Endian(sparc等)とLittle Endian(Intel等)の二つ
• ネットワーク上に流すバイト順を統一しなくてはならない
– Big Endianに統一
リトルエンディアン
16ビット整数
(short)
32ビット整数
(long)
1 2
1 2 3 4
ビッグエンディアン
2 1
4 3 2 1
ネットワーク・バイト・オーダ
• ntohs()/ntohl()
– Short, longをホストのバイトオーダに変換
• htons()/htonl()
– Short, longをネットワークバイトオーダに変換
• Inet_addr()
– “203.178.143.1”のような文字列をネットワーク
バイト・オーダーのlongに変換
今日の実習
• catプログラムを作る
– Open, read, writeの習得
• Echoクライアントを作る
– Socket, connect
– Sockaddr_in構造体
– ソケットへのread, write