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

Post on 27-Jan-2016

60 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

20 10 年秋学期 Rodney Van Meter. ネットワークプログラミング 第 7 回「ネットワークとプログラミング (2) 」. 今期の授業スケジュール(予定). 第1回 9/28 : Introduction / イントロダクション 第2回 10/5 : C Basics ~ Functions, Variables, Data Types ・ Makefiles 第3回 10/12 : C Basics ~ Command Line Arguments ・ Structures ・ Pointers - PowerPoint PPT Presentation

TRANSCRIPT

ネットワークプログラミング第 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));

top related