Makefile, TCP ソケットサーバ, コマンドライン引数
樋口さぶろお
龍谷大学理工学部数理情報学科
応用プログラミング☆実習
L11(2017-12-12 Tue)
最終更新: Time-stamp: ”2017-12-22 Fri 12:28 JST hig”
今日の目標
TCP
ソケットサーバの
(
基本的な
)
処理の流れ
を説明できる
分割コンパイルを
make
で自動化できる
エラー処理・分割コンパイル・コマンドライン引数
先週の課題から I
ポインタ
配列変数とは
,
先頭要素を指すポインタ変数
void die (char
∗message)
と
void die (char message[])
は同じ
.
引数あり関数の役立つところ
似た処理の記述を一か所にまとめる
.
異なる部分は引数に押し込める
.
main.c
1#i n c l u d e <math . h>
2/
∗
中略
∗/
3d o u b l e y , z ;
4y =1.3
∗ exp ( 1 . 3 ) ;
5p r i n t f ( ”%f
\n” , y ) ;
6z =
−3.2∗ exp ( −3.2);
7p r i n t f ( ”%f
\n” , z ) ;
↓
エラー処理・分割コンパイル・コマンドライン引数
main.c
1#i n c l u d e ” l i b . h ”
2/
∗
中略
∗/
3d o u b l e y , z ;
4y=f ( 1 . 3 ) ;
5z=f (
−3.2);
lib.h
1#i f n d e f LIB H
2#d e f i n e LIB H
3d o u b l e f ( d o u b l e x ) ;
4#e n d i f
lib.c
1#i n c l u d e <math . h>
2#i n c l u d e ” l i b . h ”
3 4d o u b l e f ( d o u b l e x )
{
5d o u b l e a ;
6a=x
∗ exp ( x ) ;
7p r i n t f ( ”%f
\n” , a ) ;
8r e t u r n a ;
9}
ここまで来たよ
10
エラー処理・分割コンパイル・コマンドライン引数
11
Makefile, TCP
ソケットサーバ
,
コマンドライン引数
TCP
ソケットサーバ
TCP ソケットクライアントの処理の流れ (再)
ソケット通信
(
ファイル入力での例え
)
関数
ソケット作成
fopen
socket
接続
fopen
connect
読み取り
/
書込
fscanf,fprintf
recv,send
接続終了
fclose
shutdown
ソケット廃棄
fclose
close
fopen-fscanf-fclose
でなく
,
低レベルファイル入出力
open-read-close
のほ
うがよく対応する
.
TCP ソケットサーバの処理の流れ
課題socket-server01ソケット通信
クライアント
サーバ
s1
ソケット作成
s=socket
s2
サーバポート指定
bind
s3
待ち受け
listen
c1
ソケット作成
sc=socket
c2
サーバに接続
connect
s4
接続受入, 通信ソケット作成
ws=accept
c3s
通信 (両方向)
send/recv
recv/send
c4s
接続終了
shutdown(sc)
shutdown(ws)
c5s
ソケット廃棄
close(sc)
close(ws)
s5
接続受入再開
s4 にもどる
待受ソケット s とは別の通信用ソケット ws を作る. s は永久に待受を続ける.
ブロック, sleeping
OS でプロセスが実行待ちの状態. 入力がくる, 出力を受け入れ
てもらえるのを待つ.
計算機システムIIひとつのクライアントと通信している間に別のクライアントが通信してく
ると
,
待ち行列に入れられる
.
その間
,
クライアントのプロセスはブロック
する
.
計算機システムII多くのクライアントを同時に相手にするには
,
サーバが
fork
システムコールで分身すればいい
.
現在のポートの状態を表示する netstat コマンド
1 $ n e t s t a t −at 2 稼 働 中 の イ ン タ ー ネ ッ ト 接 続 ( サ ー バ と 確 立 ) 3 P r o t o 受 信−Q 送 信−Q 内 部 ア ド レ ス 外 部 ア ド レ ス 状 態 4 t c p 0 0 l o c a l h o s t . l o c a l d o m : 6 0 1 0 ∗ : ∗ LISTEN 5 t c p 0 0 ∗ : m i c r o s o f t −ds ∗ : ∗ LISTEN 6 t c p 0 0 s 0 1 c d 0 5 4 2−160: s s h 1 3 3 . 8 3 . 8 3 . 7 6 : 6 5 0 0 8 ESTABLISHED 7 t c p 0 0 s 0 1 c d 0 5 4 2−160: s s h ueh−36−42. s t . ryuk :50423 ESTABLISHED 8 t c p 0 0 s 0 1 c d 0 5 4 2−160:59322 s 0 1 s v v h d 0 2 . dream . r : h t t p ESTABLISHED 9 t c p 0 0 s 0 1 c d 0 5 4 2−160:36902 i f s 3 : n f s TIME WAIT 10 t c p 0 0 s 0 1 c d 0 5 4 2−160:46408 i f s 3 : s u n r p c TIME WAIT 11 t c p 0 0 s 0 1 c d 0 5 4 2−160:59320 s 0 1 s v v h d 0 2 . dream . r : h t t p TIME WAIT 12 t c p 0 0 s 0 1 c d 0 5 4 2−160:773 i f s 3 : n f s ESTABLISHED 13 t c p 1 0 l o c a l h o s t . l o c a l d o : 5 1 0 2 0 l o c a l h o s t . l o c a l d o m a : i p p CLOSE WAIT 14 t c p 0 0 s 0 1 c d 0 5 4 2−160:59321 s 0 1 s v v h d 0 2 . dream . r : h t t p TIME WAIT 15 . . . .IP アドレスはコンピュータ (ホスト) を一意的に区別する, と言ったが例 外あり. 127.0.0.1 localhost は ‘自分’. ‘プライベートアドレス’ 10.*.*.*, 192.168.*.*, (説明してない記法)172.16.0.0/12 は内線のようなもので, ‘閉 じた’ 組織内では自由に使ってよい.
socket-server01.c
1#i n c l u d e <a r p a / i n e t . h>
2#i n c l u d e < s t d i o . h>
3#i n c l u d e < s t d l i b . h>
4#i n c l u d e < s t r i n g . h>
5#i n c l u d e <s y s / t y p e s . h>
6#i n c l u d e <s y s / s o c k e t . h>
7#i n c l u d e <s y s / u i o . h>
8#i n c l u d e < u n i s t d . h>
9 10#d e f i n e NQUEUESIZE 5
11#d e f i n e SERVER PORT 0 /
∗
コ ン パ イ ル は で き る け ど 実 行 す る 際 に は 正 し く な い
.
要 修 正
∗/
12#d e f i n e BUFFERSIZE 1000
13 14/
∗
関 数 プ ロ ト タ イ プ 宣 言
∗/
15v o i d
d i e ( c h a r m e s s a g e [ ] ) ;
16 17i n t main ( v o i d )
{
18i n t s ; /
∗
待 受 用 ソ ケ ッ ト の デ ス ク リ プ タ
∗/
19
i n t ws ; /
∗
通 信 用 ソ ケ ッ ト の デ ス ク リ プ タ
∗/
20s t r u c t
s o c k a d d r i n sa , c a ; /
∗
サ ー バ
,
ク ラ イ ア ン ト ア ド レ ス
∗/
21s o c k l e n t
c a l e n ; /
∗ t y p e d e f
で 書 か れ た 型
∗/
22i n t
m e s s a g e s i z e ;
23c h a r
r e c v b u f f e r [ BUFFERSIZE ] ;
24i n t
v a l =1;
25i n t n ;
26c h a r m e s s a g e [ BUFFERSIZE ] ;
2728
i f ( ( s=s o c k e t ( AF INET , SOCK STREAM,0))==
−1){
29d i e ( ” s o c k e t ” ) ;
30
}
31
32
/
∗
呪文
(
魔 術
)
∗/
33
i f ( s e t s o c k o p t ( s , SOL SOCKET , SO REUSEADDR,& v a l , s i z e o f
v a l ) )
{
34d i e ( ” s o c k e t o p t s ” ) ;
35}
36 37s a . s i n f a m i l y =AF INET ;
38s a . s i n p o r t = h t o n s ( SERVER PORT ) ;
39s a . s i n a d d r . s a d d r = h t o n l ( INADDR ANY ) ; /
∗ I P
ア ド レ ス 指 定 無
∗/
40
/
∗
s a . s i n z e r o [ 8 ] ;
∗/
41i f ( b i n d ( s ,
( s t r u c t
s o c k a d d r
∗)&sa , s i z e o f ( sa ))==−1){
42d i e ( ” b i n d ” ) ;
43}
44 45i f (
l i s t e n ( s , NQUEUESIZE)==
−1 ){
46d i e ( ” l i s t e n ” ) ;
47}
48 49w h i l e ( 1 )
{
50c a l e n=s i z e o f ( c a ) ;
5152
i f ( ( ws=a c c e p t ( s , ( s t r u c t
s o c k a d d r
∗)&ca , &c a l e n ))==−1){
53d i e ( ” a c c e p t ” ) ;
54}
55 56i f ( ( m e s s a g e s i z e = r e c v ( ws , r e c v b u f f e r , BUFFERSIZE , 0 ) ) < 0 )
{
57d i e ( ” r e c v ” ) ;
58}
59r e c v b u f f e r [ m e s s a g e s i z e ]= ’
\0 ’ ;
6061
i f ( s t r n c m p ( r e c v b u f f e r , ” c o u n t ” , s t r l e n ( ” c o u n t ” ) ) ! = 0 )
{
62s t r c p y ( message , ” P e n g u i n !
\ n” ) ;
63} e l s e {
64n= s t r l e n ( r e c v b u f f e r )
− s t r l e n ( ” count ” ) ;
65i f
( n==0)
{
66s t r c p y ( message , ”No A d e l i e
P e n g u i n s !
\ n” ) ;
67} e l s e i f ( n==1){
68s t r c p y ( message , ”One A d e l i e P e n g u i n !
\ n” ) ;
69} e l s e {
70s p r i n t f ( message , ”%d A d e l i e
P e n g u i n s !
\ n” , n ) ;
71}
72}
73f p r i n t f ( s t d e r r , ”%s
\n” , r e c v b u f f e r ) ;
74 75i f ( w r i t e ( ws , message ,
s t r l e n ( m e s s a g e ))==
−1){
76d i e ( ” w r i t e ” ) ;
77}
78 79i f ( s h u t d o w n ( ws , SHUT RDWR)==
−1 ){
80d i e ( ” s h u t d o w n ” ) ;
81}
82 83
i f (
c l o s e ( ws)==
−1 ){
84d i e ( ” c l o s e ” ) ;
85}
86 87}
88 89r e t u r n
0 ;
90}
91 92 93/
∗
関 数 定 義
∗/
94v o i d
d i e ( c h a r m e s s a g e [ ] )
{
95p e r r o r ( m e s s a g e ) ;
96e x i t ( 1 ) ;
97}
サーバ側関数解説 I
1#i n c l u d e <s y s / t y p e s . h>
2#i n c l u d e <s y s / s o c k e t . h>
3 4/
∗
ソケットを作るサーバクライアント共通
∗/
5i n t
s o c k e t (
略
) ;
6 7/
∗
ソケットにポート番号をつける
∗/
8i n t
b i n d ( i n t s ,
s t r u c t
s o c k a d d r
∗ sa , i n t s a l e n ) ;
9/
∗
入 力
s
ソ ケ ッ ト デ ス ク リ プ タ
, s a
サ ー バ ソ ケ ッ ト の ソ ケ ッ ト ア ド レ ス
,
s a l e n
サ イ ズ
10返 り 値 成 功
0
失 敗
−1 ∗/
11 12/
∗
13i n t
l i s t e n ( i n t s , ,
i n t
l e n q u e u e ) ;
14/
∗
入 力
s
ソ ケ ッ ト デ ス ク リ プ タ
,
l e n q u e u e
接 続 待 ち 行 列 の 長 さ
( 5
く ら い で 適 当 に
)
15返 り 値 成 功
0
失 敗
−1 ∗/
16 17サーバ側関数解説 II
18i n t
a c c e p t ( i n t s ,
s t r u c t
s o c k a d d r
∗ca , i n t ∗ c a l e n ) ;
19/
∗
入 力
s
ソ ケ ッ ト デ ス ク リ プ タ
20出 力
∗ addr
に は ク ラ イ ア ン ト の ソ ケ ッ ト ア ド レ ス
,
c a l e n
そ の サ イ ズ
,
へ の ポ イ ン タ
∗/
21返 り 値 は 通 信 用 ソ ケ ッ ト デ ス ク リ プ タ
∗/
API
sizeof 演算子
int x;
のとき
, sizeof (int), sizeof x
はバイト長
(
整数
)
を返す
常に
sizeof(char)==1
サーバクライアント両側関数解説 (再)
1#i n c l u d e <s y s / s o c k e t . h>
2 3i n t
s o c k e t ( i n t
f a m i l y ,
i n t t y p e ,
i n t
p r o t o c o l ) ;
4/
∗
ソ ケ ッ ト を 作 り
,
デ ス ク リ プ タ を 返 す
∗/
5 6i n t s h u t d o w n ( i n t
s o c k f d ,
i n t how ) ;
7/
∗
後 始 末
∗/
1#i n c l u d e < u n i s t d . h>
2i n t
c l o s e ( i n t
s o c k e t f d ) ;
3/
∗
閉 じ る
∗/
クライアント側関数解説 (再)
1#i n c l u d e <s y s / t y p e s . h>
2#i n c l u d e <s y s / s o c k e t . h>
3 4i n t
c o n n e c t ( i n t
s o c k f d ,
s t r u c t
s o c k a d d r
∗ address , i n t a d d r l e n ) ;
5/
∗
デ ス ク リ プ タ
s o c k f d
で 指 定 さ れ る ソ ケ ッ ト か ら
,
6ソ ケ ッ ト ア ド レ ス 構 造 体
a d d r e s s
で 指 定 さ れ る 通 信 先 に 接 続 要 求 を 出 す
7接 続 失 敗 な ら 負 の 返 り 値
∗/
8 9i n t
r e c v ( i n t
s o c k f d , c h a r
∗ buf , i n t len , i n t f l a g s ) ;
10/
∗ b u f
は 受 信 バ ッ フ ァ
,
l e n
は 受 信 最 大 バ イ ト 数
∗/
11/
∗
返 り 値 は 受 け 取 っ た バ イ ト 数
.
終 了 な ら
0 ,
失 敗 な ら
−1 ∗/
12 13i n t s e n d ( i n t
s o c k f d , c h a r
∗ buf , i n t len , i n t f l a g s ) ;
14/
∗ b u f
は 送 信 デ ー タ
,
l e n
は 送 信 バ イ ト 数
∗/
15/
∗
返 り 値 は 送 信 し た バ イ ト 数
.
失 敗 な ら
−1 ∗/
文字列を整数として解釈する方法 (復習)
課題 socket-client03 1c h a r s [ ] = ” 10 p e n g u i n s ” ;
2i n t n ;
3s s c a n f ( s , ”%d ” ,&n ) ;
1c h a r s [ ] = ” 10 p e n g u i n s ” ;
2i n t n ;
3n=a t o i ( s ) ; /
∗ A s c i i c h a r a c t e r TO I n t e g e r ∗/
4/
∗ a t o l , atod
な ど も あ る
∗/
エラーが起きないとすればどちらもあまり変わらない
(
が
, s
が外部
/
ユー
ザから来る場合は
,
エラーが起きないと仮定できないのだった
).
ここまで来たよ
10
エラー処理・分割コンパイル・コマンドライン引数
11
Makefile, TCP
ソケットサーバ
,
コマンドライン引数
TCP
ソケットサーバ
分割コンパイルはややこしい — make
課題 make01 1
$ c c
−o d i e . o −c d i e . c # d i e . c
ま た は
d i e . h
が 更 新 さ れ た と き
2$ c c
−o main . o −c main . c # main . c
ま た は
d i e . h
が 更 新 さ れ た と き
3$ c c
−o main d i e . o main . o −lm # main . o
ま た は
d i e . o
が 更 新 さ れ た と き
依存性と手順をファイルにメモ
.
後はそんなの計算機にまかせちゃえ
1
$ make main
ただし
,
同じディレクトリ内に依存性と手順をメモしたテキストファイル
Makefile
Makefile
1# T A B
に よ る 字 下 げ は 必 須
.
2d i e . o :
d i e . h d i e . c
3c c
−o d i e . o −c d i e . c
4 5main . o :
d i e . h main . c
6c c
−o main . o −c d i e . c
7main :
d i e . o main . o
8
c c
−o main d i e . o main . o −lm
910
h e l l o . o : h e l l o . c
11
c c
−o h e l l o . o −c h e l l o . c
12h e l l o :
h e l l o . c
Makefile の一般的記法
ルール群を書く
.
行の順序は自由
.
ターゲット間の空行自由
.
1タ ー ゲ ッ ト
1 :
依 存 フ ァ イ ル
1 1 ,
依 存 フ ァ イ ル
1 2
依 存 フ ァ イ ル
1 3
2(TAB)
タ ー ゲ ッ ト
1
を 作 る た め の 手 順
1 a
3(TAB)
タ ー ゲ ッ ト
1
を 作 る た め の 手 順
1 b
4 5タ ー ゲ ッ ト
2 : . . . .
1$ make
タ ー ゲ ッ ト
1
とされたとき
,
まず
再帰的に
1$ make
依 存 フ ァ イ ル
1 1
依 存 フ ァ イ ル
1 2
依 存 フ ァ イ ル
1 3
相当のことを行う
.
その後
,
依存ファイル
11,
依存ファイル
12,
依存ファ
イル
13
のいずれかが
,
ターゲット
1
より新しいときだけ
,
手順
1a, 1b
を
実行する
.
*.c
と
*.h
を作る手順
,
などは
make
がデフォルトルールを持っているの
で
,
省略できることがある
.
課題では無理に省略しなくてよい
.
1#
依 存 性 だ け は 人 間 が 教 え る 必 要
2d i e . o :
d i e . h d i e . c
3main . o :
d i e . h main . c
4h e l l o . o : h e l l o . c
5h e l l o :
h e l l o . c
6 7#
−lm
が 必 要 か ど う か は 人 間 が 指 定 す る 必 要
8main :
d i e . o main . o
9