ネットワークプログラミング 第 7 回「ネットワークとプログラミング (2)...
description
Transcript of ネットワークプログラミング 第 7 回「ネットワークとプログラミング (2)...
ネットワークプログラミング第 7回「ネットワークとプログラミング (2)」
20 10年秋学期Rodney Van Meter
今期の授業スケジュール(予定) 第1回 9/28 : Introduction / イントロダクション 第2回 10/5: C Basics~ Functions, Variables, Data
Types・Makefiles 第3回 10/12: C Basics~ Command Line Arguments
・ Structures ・ Pointers 第4回 10/19: C Basics~ Pointers & Arrays ・ Lists 第5回 10/26 : file I/O ・ Network Protocols 第6回 11/2 : Network Programming (1) 第7回 11/9 : Network Programming (2) 第8回 11/16 : Network Programming ( 3) 第9回 11/30 : Applied Network Programming ( 1) 第10回 12/7 : Applied Network Programming (2) 第11回 12/14 : Work on Projects 第1 2 回 12/21 : Work on Projects 第13回 1/11 : Final Presentations!!!
今日のお題 Last week’s work: TCP-success-server Lecture
TCP programming TCP-echo-client
getaddrinfo(), gethostbyname() connect()
Practice/HW: report-attendance!
Stream example (TCP)Server
socket()
bind()
Client
socket()listen()
accept()
recv()
send()
connect()
send()
recv()
Block untilconnect
Processrequest
Connection Establishmt.
Data (request)
Data (reply)
暗黙に bind()
#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;
/* make socket */????
/* give a name to the socket */????
/* set the socket address */????
/* processing */????
return 0;
}
課題:できた?
TCPプログラミング
TCP (Transmission Control Protocol)
信頼性のある通信を提供 データレート制御:不可・困難
身近な例 電子メール WEB
イメージ電話のやりとり
S:もしもし C: ○○もしもし、 です S:××です。あのさ、、、
serverclient
SYN
SYN+ACK
ACK
データ
TCP Comm Flow (server)
socket()
bind()
listen()
accept()
socket()
connect()
read()
close()
TCP client
TCP Server
write()read()
write()
read()
close()
data
data
establish
end
fork();
exit();
Socketを開いた状態
クライアントプロセス
ホスト A
サーバプロセス
ホスト B
Port B
IP Address: xx.xx.xx.xx.
Port C
Port A
Socketを開く
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の返り値
Bound to an address
クライアントプロセス
ホスト A
サーバプロセス
ホスト B
Port B
IP Address: xx.xx.xx.xx.
Port C
Port A
Proto LocalAddress ForeignAddress StateTCP *.A *.* Closed
IP Address: yy.yy.yy.yy
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))
Listen()
クライアントプロセス
ホスト A
サーバプロセス
ホスト B
Port B
IP Address: xx.xx.xx.xx.
Port C
Port A
Proto LocalAddress ForeignAddress StateTCP *.A *.* Listen
IP Address: yy.yy.yy.yy
accept() System Call int accept(int s, struct sockaddr *addr, int
*addrlen) キューで待っている接続要求を取り出して、そのクライアントと通信するためのディスクリプタを作成して、返す
clientにはクライアントの socketのアドレス、 namelenには clientのサイズ
…実際のコードでは accept(listenfd, (struct sockaddr *) &cliaddr,
&clilen) 成功なら新しい FD番号、エラーなら -1の返り値
accept()
クライアントプロセス
ホスト A
サーバプロセス
ホスト B
Port B
IP Address: xx.xx.xx.xx.IP Address: yy.yy.yy.yy
Port C
Port APort X
Connect()
Proto LocalAdddress ForeignAddress StateTCP xx.xx.xx.xx.A yy.yy.yy.yy.X Establish
accept()
クライアントプロセス
ホスト A
サーバプロセス
ホスト B
Port B
IP Address: xx.xx.xx.xx.IP Address: yy.yy.yy.yy
Port C
Port APort X
Connect()
Proto LocalAdddress ForeignAddress StateTCP *.A *.* ListenTCP xx.xx.xx.xx.A yy.yy.yy.yy.X Establish
Usage
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 code flow (client)
socket()
bind()
listen()
accept()
socket()
connect()
read()
close()
TCP client
TCP Server
write()read()
write()
read()
close()
data
data
establish
end
connect() System Call Connects this socket to the far end #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; (アドレス構造体のサイズ ) Return value:
0 on success, -1 on failure
client server
New-style naming: getaddrinfo() if (error = getaddrinfo(host, service, &hints, &ai)) {
fprintf(stderr, "getaddrinfo(%s, %s, ...): %s (%d)\n", host, service, gai_strerror(error),
error);
exit(-1);
}
/* loop through addrinfos until we get a good connect */
for (ai2 = ai; ai; ai = ai->ai_next) {
socket();
connect(fd, ai->ai_addr, ai->ai_addrlen);
/* break; once you get one that works */
}
New-style naming: getnameinfo() if (error = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf,
sizeof(hbuf), sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV)) {
fprintf(stderr, "getnameinfo(%p, %d, %p, %d, %p, %d, %d): %s(%d)\n",
ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV, gai_strerror(error), error);
continue;
}
fprintf(stdout, "Trying %s port %s...\n", hbuf, sbuf);
Using 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);
}
read() and write()
For a TCP socket, can just use read() and write() once you’re connected
Be careful about message ordering!Who is waiting on whom?
Also can use send(), recv()
Using 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);
Homework (1): TCP Client for Simple Attendance Server
Two arguments: IP address (v4 or v6) Port number
Sends student ID number
次ページにポイント説明あり
Homework (2): Proposal for Term Project
First round: Basic idea (2-3 paragraphs) 2-4 Team members (name, login
name/nickname, student ID number)
次ページにポイント説明あり
Next Week: More Complete Proposal for Term Project
“Value Proposition” (why do I care?) Related work (has it been done
before?) Key Idea How you will evaluate Schedule with technical milestones
次ページにポイント説明あり
Old style: gethostbyname() Resolves host name to IP address #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 structurestruct 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() Gets name of your host #include <unistd.h> int gethostname(char *name, size_t len); Return value: 0 on success, -1 on failure 例:
char shostname[64];
gethostname(shostname, sizeof(shostname));