ネットワークプログラミング 第7回「ネットワークとプログラミング(2)」

Slides:



Advertisements
Similar presentations
TCP/IP によるチャットプログラ ム 薄井 秀晃. 基礎知識編 TCP/IP とは? IP とは・・・ Internet Protocol の略称であり通信方法の技術的なルールで あり、実際にデータを送受信する前にデータを小さなデータ に分割し、それに発信元と受信先の IP アドレスを付加させて.
Advertisements

システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
システムコール 低水準入力 ファイルディスクリプタ ソケット
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
ネットワーク層.
システムプログラミング 第13回 情報工学科 篠埜 功.
CS-B3 ネットワークプログラミング 峰野博史
第13回 プログラミングⅡ 第13回
Windows Network Programming
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
TCPソケットプログラミング ソケットプログラミング TCP-echoのデータ通信手順
HTTPプロトコルとJSP (1) データベース論 第3回.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第11回 プロセス間通信4 仮想FTPの実現 担当:青木義満
Network Programming in C ネットワークプログラミング Lecture 8, Network Programming (3) 第8回「ネットワークとプログラミング(3)」 2010年秋学期 Rodney Van Meter.
千代浩司 高エネルギー加速器研究機構 素粒子原子核研究所
第5回ネットワークプログラミング 中村 修.
千代浩司 高エネルギー加速器研究機構 素粒子原子核研究所
千代浩司 高エネルギー加速器研究機構 素粒子原子核研究所
ネットワークプログラミング 中村 修.
第11章 UDPユーザ・データグラム・プロトコル
プログラミング論 関数ポインタ と 応用(qsort)
第11回ネットワークプログラミング 中村 修.
システムプログラミング 第13回 プロセス間通信(続き) 情報工学科 篠埜 功.
第7回ネットワークプログラミング 中村 修.
UDPエコーサーバ UDP-echoサーバのプログラムモデル(Cプログラム) サーバで利用するソケット関数(Cプログラム)
システムプログラミング 第13回 情報工学科 篠埜 功.
ネットワークプログラミング 第4回「C言語の基礎~ポインタと配列」
ソケットプログラム(TCP,UDP) EasyChat開発
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
岡村耕二 トランスポート層 ソケットプログラミング 岡村耕二 情報ネットワーク.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
ソケットプログラム(TCP,UDP) EasyChat開発2
プログラミング演習I 2003年6月25日(第10回) 木村巌.
インターネットにおける真に プライベートなネットワークの構築
ユビキタスシステムアーキテクチャ 第5回 ネットワークプログラミングの基礎
ネットワークプログラミング 第3回「C言語の基礎~コマンドライン引数・構造体・ポインタ」
UDPマルチキャストチャット    空川幸司.
第11回 プログラミングⅡ 第11回
Webプロキシ HTTP1.0 ヒント CS-B3 ネットワークプログラミング  &情報科学科実験I.
ネットワークプログラミング (3回目) 05A1302 円田 優輝.
TCP/IPとプロセス間通信 2007年1月12日 海谷 治彦.
Talkプログラムのヒント 1 CS-B3 ネットワークプログラミング  &情報科学科実験I.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
ネットワーク・プログラミング ソケットオプションとスレッド.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
Network Programming in C Lecture 6: Network Programming (1) ネットワークプログラミング 第6回「ネットワークとプログラミング(1)」 2010年秋学期 Rodney Van Meter.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
プログラミング演習I 2003年7月2日(第11回) 木村巌.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
システムプログラミング 第6回 システムコールのエラーメッセージ ファイルシステム 情報工学科 篠埜 功.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
千代浩司 高エネルギー加速器研究機構 素粒子原子核研究所
岡村耕二 TCP通信プログラム 岡村耕二 情報ネットワーク.
ネットワーク・プログラミング TCPサーバ.
ネットワーク・プログラミング ソケットプログラミングと共有メモリ.
ネットワーク・プログラミング 1対多のプロセス間通信.
岡村耕二 UDP通信プログラム 課題と回答例 岡村耕二 情報ネットワーク.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
ネットワーク・プログラミング マルチタスク.
TCP/IPの通信手順 (tcpdump)
第6章 インターネットアプリケーション 6.1 インターネットアプリケーション 6.2 Javaによるネットワーク処理 6.3 電子メール
ポートスキャン実習 2002年9月19日 修士1年 兼子 譲 牧之内研究室「インターネット実習」Webページ
プロトコル番号 長野 英彦.
岡村耕二 TCP通信プログラム 岡村耕二 情報ネットワーク.
HTTPプロトコルの詳細 M1 峯 肇史.
Presentation transcript:

ネットワークプログラミング 第7回「ネットワークとプログラミング(2)」 2008年秋学期 Rodney Van Meter

授業Webページ SFC-SFShttps://vu.sfc.keio.ac.jp/sfc- sfs/ 課題・授業資料などの情報を掲示します 本講義を「MY時間割(仮)」へ登録してください 課題・授業資料などの情報を掲示します 課題は毎回こちらに提出!! 今日の課題締め切り 6/9(月)23:59分まで!

今期の授業スケジュール(予定) 第1回:イントロダクション 第2回:C言語の基礎~関数・変数・Makefile 第5回: file I/O・ネットワークとプログラミング(1) ()‏ 第6回:ネットワークとプログラミング(1) ()‏ 第7回:ネットワークとプログラミング(2)  (11/11)‏ 第8回:ネットワークとプログラミング(3) ()‏ 第9回:応用ネットワークプログラミング(1) ()‏ 第10回:応用ネットワークプログラミング(1) ()‏ 第11回:応用ネットワークプログラミング(2) ()‏ 第12回:ミニプロ実習 ()‏ 第13回:ミニプロ最終発表()‏

今日のお題 講義 実習:TCP-echo-server作成 ネットワークプログラミング基本手順 TCPを使ったプログラミング UDP-echo-client UDP-echo-server TCPを使ったプログラミング TCP-echo-client gethostbyname()‏ connect()‏ 実習:TCP-echo-server作成

UDPプログラミング

UDP (User Datagram Protocol) server client 信頼性がない データレート制御:可 身近な例 DNS ストリーミング イメージ はがきのやりとり データ データ データ データ データ S C はがき

Datagram example (UDP)‏ Server socket()‏ Client bind()‏ socket()‏ recvfrom()‏ bind()‏ Block until Data from client sendto()‏ Data (request)‏ Process request Data (reply)‏ sendto()‏ recvfrom()‏

ソケット(Socket)‏ プロセス プロセス プロセス間通信を行う為のデータの出入り口 プロセスからはファイルディスクプリタを用いてアクセス プロセスにとってはプロセス間通信もファイル入出力も同じインタ ーフェイス プロセス プロセス socket socket

socket()システムコール int socket(int family, int type, int proto)‏ AF_INET IPv4プロトコル AF_INET6 IPv6プロトコル AF_LOCAL UNIX Domain Socket AF_ROUTE 経路制御ソケット Typeにはソケットのタイプ(以下のどれか) SOCK_STREAM ストリームソケット SOCK_DGRAM データグラムソケット SOCK_RAW rawソケット Protoにはrawソケット以外、通常0

socket()システムコール 返り値 実際のコードでは… 成功: ソケットディスクリプタが返る 失敗: -1が返る ソケットディスクリプタはファイルディスクリプタの友達 実際のコードでは… listenfd = socket(AF_INET, SOCK_STREAM, 0)‏ AF_INETの場合の利用されるIPv4の上位層 SOCK_STREAM TCP SOCK_DGRAM UDP SOCK_RAW なし

socket int socket(int domain, int type, int protocol); (例)‏ int sd; sd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)‏        AF_UNIX , SOCK_STREAM,IPPROTO_TCP SOCK_RAW,IPPROTO_ICMP

bind int bind(int sockfd,struct sockaddr *addr,int addrlen); (例)‏ struct sockaddr_in cl_addr; memset((void *)&cl_addr, 0, sizeof(cl_addr)); cl_addr.sin_family = AF_INET; cl_addr.sin_port = htons(0); cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* local host*/ bind(sd,(struct sockaddr *)&cl_addr, sizeof(cl_addr))‏

サーバのソケットアドレスを準備する struct sockaddr_in sv_addr; memset((void *)&sv_addr, 0, sizeof(sv_addr)); sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(?????); inet_aton(?????, &sv_addr.sin_addr);

inet_aton()‏ int inet_aton(const char *cp, struct in_addr *inp); アドレスを表す文字列を, ネットワークバイト順序のバイナリ値へ 「127.0.0.1 」という文字列は人間には分か りやすいが,コンピュータには分かりにくい 返り値は,指定したアドレスが正当ならば0以 外,不当なら0. 仲間 inet_ntoa()‏

inet_pton()‏ int inet_pton(int af, const char *src, void *dst); Better for IPv6 仲間 inet_ntop()‏ できれば、これを使ったほうがいい

sendto ssize_t sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, int tolen); (例) if (sendto(sd, (char *)&msg, sizeof(msg), 0 , (struct sockaddr *)&sv_addr, sizeof(sv_addr)) < 0) { perror("sendto"); exit(-1); }

recvfrom ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen); (例)‏ recvlen = recvfrom(sd, (void *)buf, 1024, 0, (struct sockaddr *)&sv_addr, &svadlen);

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #define BUFMAX 1024 int main(int argc, char *argv[]){ int sd; int cc, svadlen; char buf[BUFMAX] char rmsg[BUFMAX]; struct sockaddr_in cl_addr, sv_addr; /* socketの作成 */ ???? /* socketに名前をつける */ /* サーバのソケットアドレスの設定 */ /* 処理ルーチン(メッセージの送信,受信) */ return 0; } Sample code: UDP-echo-client(1/3) 

/* socketの作成 */ sd = socket( AF_INET, SOCK_DGRAM, 0 ); if( sd < 0 ){ perror("socket"); exit(0); } /* socketに名前をつける */ memset((void *)&cl_addr,0, sizeof(cl_addr)); cl_addr.sin_family = AF_INET; cl_addr.sin_port = htons(0); cl_addr.sin_addr.s_addr = htonl ( INADDR_ANY ); if( bind( sd, (struct sockaddr *)&cl_addr, sizeof(cl_addr)) < 0 ){ perror("bind"); /* サーバのソケットアドレスの設定 */ memset((void *)&sv_addr,0, sizeof(sv_addr)); sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(atoi(argv[2])); inet_aton(argv[1], &sv_addr.sin_addr); svadlen = sizeof(sv_addr); /* 処理ルーチン(メッセージの送信,受信) */ ???? Sample code: UDP-echo-client(2/3) 

/* 処理ルーチン(メッセージの送信,受信) */ while(1){ memset(buf, '\0', sizeof(buf)); printf("echo-client> "); fgets(buf, sizeof(buf), stdin); buf[strlen(buf)-1] = '\0'; /* send a message */ if(sendto(sofd, buf, BUFMAX, 0, (struct sockaddr *)&sv_addr, svadlen)‏ < 0) perror("sendto"); cc = recvfrom(sofd , buf, BUFMAX, 0, (struct sockaddr *)&sv_addr, &svadl en); if( cc<0) perror("recvfrom"); printf("rmsg: %s\n", buf); printf("recieve-byte: %d\n", cc); } close(sd); return 0; Sample code: UDP-echo-client(3/3) 

UDP-echo-server側 Client作成との相違点 bind()‏ recvfrom()を最初に実行 Port番号を指定する recvfrom()を最初に実行 recvfrom()でclientがデータを受け取ると,client のソケットアドレスが勝手に格納される! recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen); *fromを用いて受信したデータをsendto()する

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #define BUFMAX 1024 #define PORT_NO 55555 int main(int argc, char *argv[]){ int sd; int cc, ccadlen; char rmsg[BUFMAX]; struct sockaddr_in cl_addr, sv_addr; /* socketの作成 */ ???? /* socketに名前をつける */ /* サーバのソケットアドレスの設定 */ /* 処理ルーチン(メッセージの送信,受信) */ close(sd); return 0; } Sample code: UDP-echo-server(1/3) 

/* socketの作成 */ sd = socket( AF_INET, SOCK_DGRAM, 0 ); if( sd < 0 ){ perror("socket"); exit(0); } /* socketに名前をつける */ memset((void *)&sv_addr,0, sizeof(sv_addr)); sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(PORT_NO); sv_addr.sin_addr.s_addr = htonl ( INADDR_ANY ); if( bind( sd, (struct sockaddr *)&sv_addr, sizeof( sv_addr)) < 0 ){ perror("bind"); cadlen = sizeof(cl_addr); /* 処理ルーチン(メッセージの送信,受信) */ ???? close(sd); return 0; Sample code: UDP-echo-server(2/3) 

/* 処理ルーチン(メッセージの送信,受信) */ while(1){ /* receive a message from clients */ cc = recvfrom(sd ,rmsg, BUFMAX, 0, (struct sockaddr *)&cl_addr, &cadlen); if( cc<0) perror("recvfrom"); printf("rmsg: %s\n", rmsg); /* send a message */ if(sendto(sofd,rmsg,strlen(rmsg),0,(struct sockaddr *)&cl_addr, cadlen) < 0){ perror("sendto"); } close(sd); return 0; Sample code: UDP-echo-server(3/3) 

TCPプログラミング

TCP (Transmission Control Protocol)‏ server client 信頼性のある通信を提供 データレート制御:不可・困難 身近な例 電子メール WEB イメージ 電話のやりとり S:もしもし C:もしもし、○○です S:××です。あのさ、、、 SYN SYN+ACK ACK データ

read()システムコール int read(int d, void *buf, size t nbytes)‏ 引数 返り値 size_t nbytes: 1回のread()で読める最大バイト数(バ ッファの大きさ)‏ 返り値 int: 実際に読み込んだバイト数 0より大きい: 読み込み成功 0: ファイルの最後(EOF)に到達 0より小さい: エラー

write()システムコール int write(int d, void *buf,size t nbytes)‏ 引数 返り値 size_t nbytes: 1回のwrite()で書き込むバイト数(書き込む データの大きさ)‏ 返り値 int: 実際に書き込んだバイト数 0より大きい: 書き込み成功 0より小さい: エラー

第5回講義の資料 open()/read()/write()/close()の例 #include <fcntl.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #define BUFSIZE 1024 int main()‏ { char buf[BUFSIZE]; int fd; int nbyte; fd = open(“test.txt”, O_RDONLY, 0); while((nbyte = read(fd, buf, BUFSIZE)) > 0) { write(1, buf, nbyte); } close(fd); exit(0);

実習 TCPを用いたechoサーバを作ろう。 →次のページからに必要となる初出関数の説明 第一引数にポート番号(X)を指定しよう 先週の課題の続き! telnet localhost X でチェックしよう Wiresharkまたはtcpdumpで見ましょう 同時に二つのconnectionをできると証明して →次のページからに必要となる初出関数の説明

TCP 通信の流れ(server)‏ TCP Server socket()‏ TCP client bind()‏ socket()‏ listen()‏ establish connect()‏ accept()‏ write()‏ data read()‏ write()‏ data read()‏ read()‏ end close()‏ close()‏

Socketを開いた状態 Socketを開く クライアント プロセス サーバ プロセス Port A Port B Port C ホストA IP Address: xx.xx.xx.xx. IP Address: yy.yy.yy.yy

bind()システムコール int bind(int s, const struct sockaddr *addr, int addrlen) 用意したsocketのアドレスを実際にsocketと結びつける IPアドレスとTCP/UDPのポート番号の組 開いたソケットのステートはclosed 実際のコードでは… bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr) 成功なら0、エラーなら-1の返り値

bindした状態 Proto LocalAddress ForeignAddress State TCP *.A *.* Closed クライアント プロセス サーバ プロセス Port A Port B Port C ホストA ホストB IP Address: xx.xx.xx.xx. IP Address: yy.yy.yy.yy

listen()システムコール listen(listenfd, LISTENQ) int listen(int s, int backlog)‏ 用意したsocketを待ち受け準備状態にする ソケットの状態をCLOSEDからLISTENへ backlogはキューの長さ(backlog分の要求を保持できる)‏ accept()されるまでbacklog分のキューに保持 キューがあふれると、その要求は無視 実際のコードでは… listen(listenfd, LISTENQ) 成功なら0、エラーなら-1の返り値

Listen()‏ Proto LocalAddress ForeignAddress State TCP *.A *.* Listen クライアント プロセス サーバ プロセス Port A Port B Port C ホストA ホストB IP Address: xx.xx.xx.xx. IP Address: yy.yy.yy.yy

accept()システムコール int accept(int s, struct sockaddr *addr, int *addrlen)‏ キューで待っている接続要求を取り出して、そのクライ アントと通信するためのディスクリプタを作成して、返す clientにはクライアントのsocketのアドレス、namelen にはclientのサイズ 実際のコードでは… accept(listenfd, (struct sockaddr *) &cliaddr, &clilen) 成功なら新しいFD番号、エラーなら-1の返り値

accept()‏ Proto LocalAdddress ForeignAddress State TCP xx.xx.xx.xx.A yy.yy.yy.yy.X Establish Connect()‏ クライアント プロセス サーバ プロセス Port X Port A Port B Port C ホストA ホストB IP Address: xx.xx.xx.xx. IP Address: yy.yy.yy.yy

accept()‏ Proto LocalAdddress ForeignAddress State TCP *.A *.* Listen TCP xx.xx.xx.xx.A yy.yy.yy.yy.X Establish Connect()‏ クライアント プロセス サーバ プロセス Port X Port A Port B Port C ホストA ホストB IP Address: xx.xx.xx.xx. IP Address: yy.yy.yy.yy

使い方例 int socket_fd, accept_fd; int client_addrlen; int readlen; struct sockaddr_in server, client; socket_fd = socket(AF_INET,SOCK_STREAM, 0); memset((void *)&server, 0, sizeof(server)); bind(socket_fd,  (struct sockaddr *)&server,  sizeof(struct sockaddr_in)); listen(socket_fd, 5); memset((void *)&client, 0, sizeof(client)); client_addrlen = sizeof(client)‏ accept_fd = accept(socket_fd,(struct sockaddr *)&client, (int *)&client_addrlen);    ---(read/writeなどの処理)---- close(accept_fd); close(socket_fd); }

実習:それでは作ってみましょう! TCPを用いたechoサーバを作ろう。 第一引数にポート番号を指定しよう

TCP 通信の流れ(client)‏ TCP Server socket()‏ TCP client bind()‏ socket()‏ listen()‏ establish connect()‏ accept()‏ write()‏ data read()‏ write()‏ data read()‏ read()‏ end close()‏ close()‏

connect()システムコール 別のソケットとの接続要求 #include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); int sockfd; (ソケット記述子)‏ struct sockaddr *serv_addr; (プロトコル対応のアドレ ス構造体へのポインタ)‏ socklen_t addrlen; (アドレス構造体のサイズ)‏ 返り値 接続に成功するとゼロを返す.失敗すると-1を返す client server

課題:tcpでechoクライアント TCPでechoクライアントを書いて見ましょう 第一引数にホスト名,第2引数にポート番号を指定 自分のサーバにアクセス 次ページにポイント説明あり

gethostbyname()‏ ホスト名からIPアドレスを得る #include <unistd.h> struct hostent gethostname(const char *name); 例 struct sockaddr_in sin; struct hostent *shost; shost = gethostbyname(argv[1]); sin.sin_addr = *(struct in_addr *)hp->h_addr;

sample #include <netdb.h> int main (int argc, char *argv[] ) { int sock_fd; struct sockaddr_in sin; char buf[BUF_SIZE]; int readlen; struct hostent *hp; hp = gethostbyname( argv[1] ); /* add */ sock_fd = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(SERV_PORT); sin.sin_addr = *(struct in_addr *)hp->h_addr; }

hostent構造体 struct hostent{ char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype /* host address type */ int h_length /* length of address */ char **h_addr_list; /* list of addresses                                           */ } #define h_addr h_addr_list[0] /* for backward compatibility

練習: ポイント sock_fd = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(SERV_PORT); sin.sin_addr = *(struct in_addr *)hp->h_addr; connect(sock_fd, (struct sockaddr *)&sin, sizeof(sin)); fgets(buf,sizeof(buf),stdin); write(sock_fd, buf, readlen); readlen = read(sock_fd, buf, sizeof(buf)); printf("%s\n",buf);

gethostname()‏ ホスト名を取得する #include <unistd.h> int gethostname(char *name, size_t len); 返り値:成功した場合0,失敗した場合-1が返る 例: char shostname[64]; gethostname(shostname, sizeof(shostname));