応用プログラミング I 7/6
1
送信元確認
元(UDP トランシーバサンプル) 変更部分 課題 18
//recvrecvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
fputs(buf, stdout);
if(buf[0]=='.') break;
//recv do {
recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
} while (guest.sin_addr.s_addr==target.sin_addr.s_addr);
printf("[%s]", inet_ntoa(guest.sin_addr));
fputs(buf, stdout);
if(buf[0]=='.') break;
受信拒否メッセージ
変更部分 課題 18
//recvfor(;;) {
recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
if(guest.sin_addr.s_addr==target.sin_addr.s_addr) { break; } bytes=sprintf(buf, "#Sorry. This host is busy.¥n");
sendto(sock, buf, bytes+1, 0, (SOCKADDR*)&guest, lenGuest);
}
printf("[%s]", inet_ntoa(guest.sin_addr));
fputs(buf, stdout);
if(buf[0]=='.') break;
ローカルホスト ポート間通信
課題 18 変更部分
char targetad[16]="157.105.208.28"; // 接続相手 int port=9000;
char targetad[16]="127.0.0.1"; // ローカルホスト int port, myport;
printf("my port:");
scanf("%d", &myport);
printf("target port:");
scanf("%d", &port);
scanf("%*c");
SOCKADDR_IN local={AF_INET, htons(port),
{INADDR_ANY}}; SOCKADDR_IN local={AF_INET, htons(myport),
{INADDR_ANY}};
//recv do {
recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
} while (
guest.sin_addr.s_addr==target.sin_addr.s_addr );
printf("[%s]", inet_ntoa(guest.sin_addr));
//recv do {
recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
} while (
guest.sin_addr.s_addr==target.sin_addr.s_addr
&& guest.sin_port==target.sin_port );
printf("[%s:%d]", inet_ntoa(guest.sin_addr), ntohs(guest.sin_port)); // 要バイトオーダー変換
応用プログラミング I 7/6
2
プロトコル
通信形式・手順の取り決め。プロトコルに従うソフトであれば,同一のソフトでなくても(他社製のソ フト等)通信ができる。
例:UDP トランシーバーのプロトコル
先手 後手
1.
開始メッセージを送信
(相手の接続待ち)
2.
相手のメッセージを受信
3.(自分のメッセージを作成)
自分のメッセージを送信
(相手の送信待ち)
4.
(以下
2~3の繰り返し)
×(起動していないので破棄される)
1.
開始メッセージを送信
(相手の送信待ち)
2.
相手のメッセージを受信
3.(自分のメッセージを作成)
自分のメッセージを送信
(相手の送信待ち)
4.
(以下
2~3の繰り返し)
文字列以外の情報の送信
sendA()による送信は文字列で行われましたが,数値も文字列に変換することで送信することができる。
文字列と数値の相互変換には
sprintf,sscanfを使うと便利である。
機能 バッファの文字配列に
printfの形式で文字列を出力する 形式
int sprintf(char *buf, char *formatstr, ... );引数
buf:出力先のバッファ(文字配列),formatstr:出力書式文字列
以降に,出力したい任意の数の変数が続く 戻り値 出力バイト数
ヘッダ string.h
機能 バッファの文字配列から
scanfの形式で値を抽出する 形式
int scanf(char *buf, char *formatstr, ... );引数
buf:入力元のバッファ(文字配列),formatstr:入力書式文字列
以降に,入力する任意の数の変数ポインタが続く 戻り値 入力に成功した項目数
ヘッダ string.h
応用プログラミング I 7/6
3
課題 19
魚の骨(仮称)ゲームのルールは以下のようなものである。
右のような魚の絵から, 「D@+++++++++++」
双方お互いに尻尾から
1~3本の骨(文字)を抜いていって,頭(@)を抜くことになった方の負け。
(「+」の骨は,初めにお互いのプレイヤーが任意の個数描き込むものとする)
これから以下のようなプロトコルを考えた。これを実装しなさい。
ポートは
9010,9011番を利用する。 (9011 番はローカルテスト用)
先にプログラムを開始した方を先手とし,後にプログラムを開始した方を後手とする。
まず先手の立場を考える。
1.
先手は,後手にゲーム開始の合図(FIRST)を送る(後手が開始していないので破棄される) 。
2.先手は,後手からゲーム開始の合図(FIRST)を受信した場合ゲームを始める。
3.
先手は,後手に合図(SECOND)を送信する。
4.
先手は,後手に自分の描き込む骨(+)の数(N1)を送信する。
5.
先手は,後手から描き込む骨(+)の数(N2)を受信する(N=N1+N2+2 が骨の数となる) 。
6.(画面に骨を表示し,抜く骨の数の入力を受け付ける)
抜く骨の数 (1~3)を後手に送信する。残りの骨数
Nを更新する。
頭を抜いた場合(残り骨数
N<2)は相手の勝ち(YOUWIN)を送信し(自分の負けを表示し)終了する。
7.
先手は後手が抜いた骨の数を受信し,残りの骨数
Nを更新する。
もし(YOUWIN)を受信した場合, (自分の勝ちを表示し)終了する。
8. 5
から繰り返す。
後手の立場は,以下のようになる。
1.
(なし)
2.
後手は,後手にゲーム開始の合図(PLAY)を送る。
3.
後手は,先手から合図(SECOND)を受け取る。
4.
後手は,自分の書き込む骨の数(N2)を送信する。
5.
後手は,先手の書き込んだ骨の数(N1)を受信する。
6.