Download presentation
Presentation is loading. Please wait.
1
Network Programming: http://network.hanbat.ac.kr
2
소켓 (socket) 이란 ? The interface that the OS provides to its networking subsystem application layer transport layer (TCP/UDP) network layer (IP) link layer (e.g. ethernet) application layer transport layer (TCP/UDP) network layer (IP) link layer (e.g. ethernet) User Process Socket Internet http://network.hanbat.ac.kr2 Application Socket API TCPUDP...
3
Two Types of Application Processes Communication Datagram Socket (UDP) Collection of messages Connectionless sendto, recvfrom No error/flow control Best effort Stream Socket (TCP) Stream of bytes Connection-oriented connect… send, recv disconnect Error/flow control Reliable http://network.hanbat.ac.kr3
4
Clients and Servers http://network.hanbat.ac.kr4 Client program – Running on end host – Requests service – E.g., Web browser Server program – Running on end host – Provides service – E.g., Web server GET /index.html “Site under construction”
5
http://network.hanbat.ac.kr5 Client “sometimes on” – Initiates a request to the server when interested Web browser on your laptop or cell phone – Doesn’t communicate directly with other clients – Needs to know server’s address Server is “always on” – Handles services requests from many client hosts Web server for the www.cnn.com – Doesn’t initiate contact with the clients – Needs fixed, known address GET /index.html “Site under construction”
6
Socket Addresses Popular applications have well-known ports E.g., port 80 for Web and port 25 for e-mail /etc/services Port # in TCP/UDP packet header Destination port #, source port # Well-known vs. ephemeral ports Server has a well-known port (e.g., port 80 for http) Between 0 and 1023 (requires root to use) Client picks an unused ephemeral (i.e., temporary) port Between 1024 and 65535 http://network.hanbat.ac.kr6
7
Uniquely identifying traffic between the hosts Two IP addresses and two port numbers Source/destination IP address Source/destination port Underlying transport protocol (e.g., TCP or UDP) http://network.hanbat.ac.kr7 Connection socket pair (128.2.194.242:3479, 208.216.181.15:80) HTTP Server (port 80) Client Client socket address 128.2.194.242:3479 Server socket address 208.216.181.15:80 Client host address 128.2.194.242 Server host address 208.216.181.15 FTP Server (port 21)
8
Socket Server and Client exchange messages over the network through a common Socket API http://network.hanbat.ac.kr8 TCP/UDP IP Ethernet Adapter Server TCP/UDP IP Ethernet Adapter Clients Socket API hardware kernel space user space ports Application Socket API TCPUDP...
9
struct sockaddr http://network.hanbat.ac.kr9 The generic: struct sockaddr { u_short sa_family; char sa_data[14]; }; sa_family specifies which address family is being used determines how the remaining 14 bytes are used The Internet-specific: struct sockaddr_in { sin_family short sin_family; sin_port u_short sin_port; sin_addr struct in_addr sin_addr; char sin_zero[8]; }; sin_family = AF_INET (PF_INET) sin_port: port # (0~65535) sin_addr: IP address sin_zero: unused struct in_addr { // IP addr. __be32 s_addr; // 32 bits };
10
Byte Ordering What would happen if two computers with different integer byte ordering communicate? … different CPU Example sizeof(int) 4 http://network.hanbat.ac.kr10 89 67 F5 E4 D3 C2 B1 A0 Big-Endian Little-Endian 0 MAX address int * lptr; (* lptr) = 0x8967F5E4;(* lptr) = 0xE4F56789; lptr + 1 100 101 102 103
11
http://network.hanbat.ac.kr11 Big-Endian Little-Endian Motorola 68xx, 680x0 Intel IBM Hewlett-Packard DEC VAX Internet TCP/IP Sun SuperSPARC Bi-Endian Motorola Power PC Silicon Graphics MIPS RS 232 AMD
12
Introduction of a network byte order. Big endian uint16_thtons (uint16_thost16bitvalue) uint32_thtonl (uint32_thost32bitvalue) uint16_tntohs (uint16_tnet16bitvalue) uint32_tntohl (uint32_tnet32bitvalue) For port numbers and IP addresses http://network.hanbat.ac.kr12
13
Byte Manipulation Functions #include void bzero (void *dest, int n); 반환값 : 없음 void bcopy (const void *src, void *dest, int n); 반환값 : 없음 int bcmp (const void *ptr1, const void *ptr2, int n); 반환값 : 같으면 0, 같지 않으면 0 이 아닌 정수 http://network.hanbat.ac.kr13
14
#include void *memset (void *dest, int c, int n); 반환값 : 메모리 영역 dest 에 대한 포인터 void *memcpy (void *dest, const void *src, int n); 반환값 : 메모리 영역 dest 에 대한 포인터 int memcmp (const void *ptr1, const void *ptr2, int n); 반환값 : 같으면 0, 같지 않으면 음의 정수 또는 양의 정수 http://network.hanbat.ac.kr14
15
Address Conversion Functions #include int inet_aton (const char *strptr, struct in_addr *addrptr); 문자열 IP address (strptr) 를 in_addr 구조체로 변환 반환값 : 성공시 1, 에러시 0 in_addr_t inet_addr (const char *strptr); 문자열 IP addres (strptr) 를 network-byte order 의 바이너리 데이터 (in_addr_t 타입 ) 로 변경하여 리턴 반환값 성공시 32-bit network byte ordered IPv4 주소 에러시 INADDR_NONE char *inet_ntoa (struct in_addr inaddr); Network-byte order 의 바이너리 주소를 ( 문자열 ) IP address 로 변경 반환값 : dotted-decimal 문자열 포인터 ※ a = ascii, n = numeric http://network.hanbat.ac.kr15 “192.168.1.2”
16
int inet_pton (int af, const char *src, void *dst); converts the character string src into a network address structure in the af address family. (IPv4, IPv6 지원 ) const char *inet_ntop (int af, const void *src, char *dst, socklen_t size); converts the network address structure src in the af address family into a character string. (IPv4, IPv6 지원 ) #include void main(int argc, char *argv[]) { struct in_addr addr; char buf[20]; printf ("demical IP addr : %s\n", argv[1]); inet_pton (AF_INET, argv[1], &addr.s_addr); // “192.168.10.1” binary printf ("inet_pton(%s) : 0x%x\n", argv[1], addr.s_addr); inet_ntop (AF_INET, &addr.s_addr, buf, sizeof(buf)); printf ("inet_ntop(0x%x) = %s\n", addr.s_addr, buf); } http://network.hanbat.ac.kr16 “192.168.1.2”
17
#include main() { struct sockaddr_in antelope; char *some_addr; inet_aton ("10.0.0.1", &antelope.sin_addr); // store IP in antelope some_addr = inet_ntoa (antelope.sin_addr); // return the IP printf ("%s\n", some_addr);// prints "10.0.0.1" // and this call is the same as the inet_aton() call, above: antelope.sin_addr.s_addr = inet_addr ("10.0.0.1"); } http://network.hanbat.ac.kr17
18
호스트 정보를 얻기 위한 함수 #include struct hostent *gethostbyname (const char *hostname); 문자열 hostname 의 노드에 대한 정보를 리턴 (struct hostent * 타입 ) “network.hanbat.ac.kr” 210.110.249.28 struct hostent { char*h_name;/* 공식적인 호스트 이름 */ char **h_aliases;/* 호스트의 별칭 목록 */ int h_addrtype;/* 호스트 주소 타입 : AF_INET or AF_INET6 */ int h_length;/* 호스트 주소의 길이 : IPv4 의 경우 4 */ char **h_addr_list;/* 호스트 주소 목록, numeric */ }; http://network.hanbat.ac.kr18
19
http://network.hanbat.ac.kr19 #include int main (int argc, char *argv[]) { int i; struct hostent *he; struct in_addr **addr_list;
20
http://network.hanbat.ac.kr20 if ((he = gethostbyname(argv[1])) == NULL) { herror("gethostbyname"); return 2; } printf("Official name is: %s\n", he->h_name); printf(" IP addresses: "); addr_list = (struct in_addr **)he->h_addr_list; for(i = 0; addr_list[i] != NULL; i++) { printf("%s \n", inet_ntoa(*addr_list[i])); } printf("\n"); } 실습 16, 17, 19~20
21
struct hostent *gethostbyaddr (const char *addr, int len, int family); 이진 IP 주소를 사용하여 그 주소에 해당하는 호스트 이름을 찾는다. addr. char * 타입이지만 사실은 in_addr 구조체의 포인터 주소이다 len. IP 주소의 크기이다. IPv4 의 경우는 4 Family 주소 체계를 나타낸다. IPv4 의 경우는 AF_INET 202.30.46.38 (binary address) “www.hanbat.ac.kr” http://network.hanbat.ac.kr21
22
http://network.hanbat.ac.kr22 #include int main (int argc, char *argv[]) { struct hostent *he; struct in_addr addr; inet_aton(argv[1], &addr); he = gethostbyaddr(&addr, sizeof(addr), AF_INET); printf("Host name: %s\n", he->h_name); }
23
#include int gethostname (char *retName, int namelen); 현재의 호스트 이름을 반환 http://network.hanbat.ac.kr23
24
http://network.hanbat.ac.kr24 #include main(int argc, char **argv) { char hostname[128]; gethostname(hostname, sizeof(hostname)); printf("My hostname: %s\n", hostname); } 실습 22, 24
25
http://network.hanbat.ac.kr25
26
#include main(int argc, char *argv[]) { struct in_addr ip; struct hostent *hostentry; char str[50]; if (argc != 2){ printf("Usage: address_conversion [ Ip address ]\n"); exit(0); } http://network.hanbat.ac.kr26
27
inet_aton(argv[1], &ip); printf("Dotted_decimal to Binary_IP = \t%X\n", ip); hostentry=gethostbyaddr((char *)&ip, sizeof(ip), AF_INET); printf("Binary_IP to Domain_name = \t%s\n", hostentry->h_name); memcpy(str, hostentry->h_name, strlen(hostentry->h_name)); // copy host name to str str[strlen(hostentry->h_name)] = '\0'; memset(hostentry, 0, sizeof(struct hostent));// clear hostentry memset(&ip, 0, sizeof(ip));// clear ip hostentry=gethostbyname(str); memcpy(&ip.s_addr, hostentry->h_addr_list[0], sizeof(ip.s_addr));// set ip.s_addr printf("Domain_name to Binary_IP = \t%X\n", ip); printf("Binary_IP to Dotted_decimal = \t%s\n", inet_ntoa(ip)); } http://network.hanbat.ac.kr27
28
http://network.hanbat.ac.kr28 실습
29
서비스 정보를 얻기 위한 함수 #include struct servent *getservbyname (const char *servname, const char *protoname); 반환값 성공시 호스트의 정보가 담긴 구조체 포인터 에러시 NULL struct servent *sptr; sptr = getservbyname (“domain”, “udp”); sptr = getservbyname (“ftp”, “tcp”); sptr = getservbyname (“ftp”, NULL); sptr = getservbyname (“ftp”, “udp”);// 에러. ftp 는 udp 를 사용하지 않는다 */ http://network.hanbat.ac.kr29 struct servent{ char *s_name;/* 공식적인 서비스 이름 */ char **s_aliases;/* 별칭 목록 */ int s_port;/* 포트번호, network-byte order */ char *s_proto;/* 사용되는 프로토콜 */ };
30
#include struct servent *getservbyport (int port, const char *protoname); 반환값 성공시 호스트의 정보가 담긴 구조체 포인터 에러시 NULL struct servent*sptr; sptr = getservbyport (htons(53), “udp”); sptr = getservbyport (htons(21), “tcp”); sptr = getservbyport (htons(21), NULL); sptr = getservbyport (htons(21), “udp”);// 에러. ftp 는 udp 를 사용하지 않는다 http://network.hanbat.ac.kr30
31
#include main(int argc, char *argv[]) { struct in_addr ip; struct servent *service; int port; if (argc != 3) { printf("Usage: getservice [service] [port]\n"); exit(0); } http://network.hanbat.ac.kr31
32
if ( (service = getservbyname(argv[1], NULL)) == NULL) { printf("getservbyname error\n"); exit(-1); } port = ntohs(service->s_port); printf("%s port number: %d(%s)\n", service->s_name, port, service->s_proto); memset(service, 0, sizeof(struct servent)); port = htons(atoi(argv[2])); if ((service = getservbyport(port, NULL)) == NULL) { printf("getservbyname error\n"); exit(-1); } printf("port %d(%s) : %s service\n", ntohs(service->s_port), service->s_proto, service->s_name ); } http://network.hanbat.ac.kr32 실습
33
SOCKET API http://network.hanbat.ac.kr33
34
전체 과정 above TCP http://network.hanbat.ac.kr34
35
Above UDP http://network.hanbat.ac.kr35
36
기본적인 소켓 함수들 #include int socket (int family, int type, int protocol); Create socket 반환값 : 성공시 소켓 기술자, 에러시 -1 Familytype Protocol 일반적으로 0 http://network.hanbat.ac.kr36 family 설 명 AF_INET AF_INET6 AF_LOCAL AF_ROUTE AF_KEY AF_ISO IPv4 protocols IPv6 protocols Unix domain protocols Routing sockets Key socket OSI protocols type 설 명 SOCK_STREAM SOCK_DGRAM SOCK_RAW Stream socket (TCP) Datagram socket (UDP) Raw socket Application Socket API TCPUDP...
37
#include int connect (int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); Client 가 수행 Connect to server (in servaddr) 반환값 : 성공시 0, 에러시 -1 http://network.hanbat.ac.kr37
38
#include int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); Server 가 실행 Bind address/port (in myaddr) to socket (in sockfd) 반환값 : 성공시 0, 에러시 -1 Wildcard 주소의 예 struct sockaddr_in servaddr; servaddr.sin_addr.s_addr = htonl (INADDR_ANY); /* wildcard */ 자신의 IP 주소를 자동적으로 찾아줌 여러 개의 NIC 을 가지고 있는 경우 각 NIC 에는 하나씩의 IP 주소가 할당됨 이때, INADDR_ANY 는 모든 NIC 에 할당된 IP 주소들 전체를 의미 http://network.hanbat.ac.kr38
39
Many client requests may arrive Server cannot handle them all at the same time Server could reject the requests, or let them wait #include int listen (int sockfd, int backlog); Server 가 실행 backlog Define how many connections can be pending Listen is non-blocking returns immediately 반환값 성공시 0 에러시 -1 http://network.hanbat.ac.kr39
40
Server Waits for connection request to arrive Blocking until the request arrives And then accepting the new request #include int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); Server 가 실행 Accept a new connection from a client 반환값 새로운 연결소켓 기술자 에러시 -1 리턴 후, cliaddr 에는 연결한 클라이언트의 주소 정보가 저장된다. http://network.hanbat.ac.kr40
41
#include int close (int sockfd); (read, write 를 포함하는 ) sockfd 의 종료 반환값 : 성공시 0, 에러시 -1 int shutdown (int sockfd, int howto); sockfd 의 종료 close 보다 미세한 조정 가능 Howto SHUT_RD : 읽기만을 종료 SHUT_WR : 쓰기만을 종료 SHUT_RDWR : 읽기 / 쓰기 모두 종료 반환값 : 성공시 0, 에러시 -1 http://network.hanbat.ac.kr41
42
데이터의 송수신을 처리하기 위한 함수들 #include int write (int sockfd, const void *buff, int nbytes); TCP 반환값 : 성공시 송신된 실제 바이트 수, 에러시 -1 #include int send (int sockfd, const void *buff, int nbytes, int flags); TCP int sendto (int sockfd, const void *buff, int nbytes, int flags, const struct sockaddr *to, socklen_t addrlen); UDP 반환값 : 성공시 송신된 실제 바이트 수, 에러시 -1 http://network.hanbat.ac.kr42
43
Flags 보통의 경우는 0 http://network.hanbat.ac.kr43 flags 설명 recv/send MSG_DONTROUTE 경로배정 처리를 하지 않는다.( 소켓 옵션참고 ) send MSG_DONTWAIT send, sendto, recv, recvfrom 함수에서 blocking 되지 않는다. recv/send MSG_OOB 대역외 데이터의 송수신시 사용된다. recv/send MSG_PEEK recv 혹은 recvfrom 함수 호출이 끝난 후 시스템이 데이터를 버리지 않고 살펴볼 수 있게 한다. recv MSG_WAITALL 수신 함수에 지정한 바이트만큼 읽기 전에는 함수에서 돌아오지 못하도록 지시한다. recv
44
#include int read (int sockfd, void *buff, int nbytes); TCP 반환값 : 성공시 수신된 실제 바이트 수, 에러시 -1 #include int recv (int sockfd, void *buff, int nbytes, int flags); TCP int recvfrom (int sockfd, void *buff, int nbytes, int flags, struct sockaddr *from, socklen_t *addrlen); UDP 데이터가 수신되면, ( 데이터를 송신한 ) 상대방의 주소가 from 에 저장된다. http://network.hanbat.ac.kr44
45
TCP EXAMPLES http://network.hanbat.ac.kr45
46
Simple socket example Basically the client connects to the server, the server sends the message “Hello World”, and the client prints the received message. http://network.hanbat.ac.kr46 connection Client Server “Hello World” “Hello world”
47
simpleServer.c #include int main(){ int welcomeSocket, newSocket; char buffer[1024]; struct sockaddr_in serverAddr; struct sockaddr_in serverStorage; socklen_t addr_size; /*---- Create the socket. ----*/ welcomeSocket = socket(AF_INET, SOCK_STREAM, 0); http://network.hanbat.ac.kr47
48
/*---- Configure settings of the server address struct ----*/ serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(7891); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(serverAddr.sin_zero, '\0', sizeof (serverAddr.sin_zero)); /*---- Bind the address struct to the socket ----*/ bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)); /*---- Listen on the socket, with 5 max connection requests queued ----*/ if(listen(welcomeSocket, 5)==0) printf("Listening\n"); else printf("Error\n"); http://network.hanbat.ac.kr48
49
/*---- Accept call creates a new socket for the incoming connection ----*/ addr_size = sizeof (serverStorage); newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size); /*---- Send message to the socket of the incoming connection ----*/ strcpy(buffer, "Hello World\n"); send(newSocket, buffer, 13, 0); } http://network.hanbat.ac.kr49
50
simpleClient.c #include int main(){ int clientSocket; char buffer[1024]; struct sockaddr_in serverAddr; socklen_t addr_size; /*---- Create the socket. ----*/ clientSocket = socket(AF_INET, SOCK_STREAM, 0); http://network.hanbat.ac.kr50
51
/*---- Configure settings of the server address struct ----*/ serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(7891); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(serverAddr.sin_zero, '\0', sizeof (serverAddr.sin_zero)); /*---- Connect the socket to the server using the address struct ----*/ addr_size = sizeof (serverAddr); connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size); /*---- Read the message from the server into the buffer ----*/ recv(clientSocket, buffer, 1024, 0); /*---- Print the received message ----*/ printf("Data received: %s", buffer); } http://network.hanbat.ac.kr51
52
http://network.hanbat.ac.kr52 실습
53
Iterative daytime 서버와 클라이언트 http://network.hanbat.ac.kr53 connection Client Server time Print time “connection from...” Get time
54
Iterative daytime 서버와 클라이언트 inet.h #include http://network.hanbat.ac.kr54
55
daytime server - daytime_ser_tcp.c #include "inet.h" #include #define MSGLEN 128 int main(int argc, char *argv[]) { int sockfd, confd; struct sockaddr_in servaddr, cliaddr; int len; char buf[MSGLEN]; time_t date; if (argc != 2) { printf("Usage: daytime_ser [Port number]\n"); exit(0); } http://network.hanbat.ac.kr55
56
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("server: can't create socket\n"); exit(-1); } servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wild card */ servaddr.sin_port = htons(atoi(argv[1])); if ( (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0){ printf("server: bind error\n"); exit(-1); } listen(sockfd, 5); http://network.hanbat.ac.kr56
57
while(1) { len = sizeof(cliaddr); confd = accept(sockfd, (struct sockaddr *)&cliaddr, &len); if (confd < 0) { printf("server: accept error\n"); exit(-1); } printf("connection from %s, port %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, buf, sizeof(buf)), ntohs(cliaddr.sin_port)); date = time(NULL);// date the number of seconds since the 1970-01-01-0-0 memset(buf, '\0', sizeof(buf)); sprintf(buf, "%s", ctime(&date)); // buf calendar time (“ Mon Aug 13 08:23:14 2012 “) send(confd, buf, strlen(buf), 0); close(confd); } http://network.hanbat.ac.kr57
58
daytime client - daytime_cli_tcp.c #include "inet.h" #include #define MSGLEN 128 int main(int argc, char *argv[]) { int sockfd, clifd; struct sockaddr_in servaddr; int len; char buf[MSGLEN]; time_t date; if (argc != 3){ printf("Usage: daytime_cli [Server IP] [Port number]\n"); exit(0); } http://network.hanbat.ac.kr58
59
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("client: can't create socket\n"); exit(-1); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(argv[1]);// server ip addr servaddr.sin_port = htons(atoi(argv[2]));// server port # if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){ printf("client: can't connect\n"); exit(-1); } http://network.hanbat.ac.kr59
60
memset(buf, '\0', sizeof(buf)); while( (len=recv(sockfd, buf, MSGLEN, 0)) > 0){ buf[len]= '\0'; printf("%s", buf); } close(sockfd); } http://network.hanbat.ac.kr60
61
http://network.hanbat.ac.kr61 실습
62
Echo client/server http://network.hanbat.ac.kr62 connection Client Server echoed data Print Read from socket echo Read from KB data
63
echoServer.c /*Required Headers*/ #include int main() { char str[100]; int listen_fd, comm_fd; struct sockaddr_in servaddr; http://network.hanbat.ac.kr63
64
listen_fd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(22000); bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); listen(listen_fd, 10); comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL); http://network.hanbat.ac.kr64
65
while (1) { bzero(str, 100); read(comm_fd, str, 100); printf("Echoing back - %s", str); write(comm_fd, str, strlen(str)+1); } http://network.hanbat.ac.kr65
66
echoClient.c #include int main(int argc,char **argv) { int sockfd,n; char sendline[100]; char recvline[100]; struct sockaddr_in servaddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof (servaddr)); http://network.hanbat.ac.kr66
67
servaddr.sin_family = AF_INET; servaddr.sin_port = htons(22000); inet_pton(AF_INET, "127.0.0.1", &(servaddr.sin_addr)); connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while(1) { bzero(sendline, 100); bzero(recvline, 100); fgets(sendline, 100, stdin); /*stdin = 0, standard input */ write(sockfd, sendline, strlen(sendline)+1); read(sockfd, recvline, 100); printf("%s", recvline); } http://network.hanbat.ac.kr67
68
execution http://network.hanbat.ac.kr68 실습
69
과제 클라이언트와 서버 프로세스간 1:1 로 통신하는 채팅 프로그램을 작성하라. 클라이언트가 키보드로 입력한 메시지는 서버에게 출력되고, 서버가 키보드로 입력한 메시지는 클라이언트에게 출력된다. 클라이언트와 서버는 번갈아 가면서 메시지를 입력한다. http://network.hanbat.ac.kr69
70
http://network.hanbat.ac.kr70 connection Client Server data Print read data Read from KB data 실습
71
chatServer.c #include int main(int argc, char *argv[]) { int socket_desc, client_sock, c, read_size, portno; struct sockaddr_in server, client; char client_message[100], msg[100]; http://network.hanbat.ac.kr71
72
if (argc < 2) { printf("chatServer port#\n"); exit(0); } portno = atoi(argv[1]); bzero((char *) &server, sizeof(server)); //Create socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Could not create socket"); } //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(portno); http://network.hanbat.ac.kr72
73
//Bind if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) { perror("bind failed. Error"); return 1; } listen(socket_desc, 3); printf("Waiting for incoming connections...\n"); c = sizeof(struct sockaddr_in); //accept connection from an incoming client client_sock = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) & c); if (client_sock < 0) { perror("accept failed"); return 1; } printf("Connection accepted\n"); http://network.hanbat.ac.kr73
74
//Receive a message from client bzero(&client_message, sizeof(client_message)); while ((read_size = recv(client_sock, client_message, 100, 0)) > 0) { printf("Client message: %s", client_message); printf("Enter msg to sent to client: "); bzero(&msg, sizeof(msg)); fgets(msg, 100, stdin); //Send the message back to client if (write(client_sock, msg, sizeof(msg)) < 0) { puts("Sorry message failed, Client disconnected"); break; } bzero(&client_message, sizeof(client_message)); } http://network.hanbat.ac.kr74
75
if (read_size == 0) { puts("Client disconnected"); fflush(stdout); } else if (read_size == -1) { perror("recv failed"); } return 0; } http://network.hanbat.ac.kr75
76
chatClient.c #include int main(int argc, char *argv[]) { int sock, portno; struct sockaddr_in server; struct hostent *host; char message[100], server_reply[100]; if (argc < 3) { printf("chatClient serverIP serverPort\n"); exit(0); } http://network.hanbat.ac.kr76
77
portno = atoi(argv[2]); host = gethostbyname(argv[1]); if (!host) { herror(argv[1]); exit(-1); } //Create socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("Could not create socket"); } puts("Socket created"); server.sin_addr.s_addr = *(long *) (host->h_addr); server.sin_family = AF_INET; server.sin_port = htons(portno); http://network.hanbat.ac.kr77
78
//Connect to remote server if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } printf("Connected\n"); printf("Enter message: "); bzero(&message, sizeof(message)); fgets(message, 100, stdin); //Send some data if (send(sock, message, strlen(message), 0) < 0) { puts("Send failed"); return 1; } bzero(&server_reply, sizeof(server_reply)); http://network.hanbat.ac.kr78
79
//Receive a reply from the server while (recv(sock, server_reply, 100, 0) > 0) { printf("Server reply : %s", server_reply); bzero(&server_reply, sizeof(server_reply)); printf("Enter message('bye' to quit): "); bzero(&message, sizeof(message)); fgets(message, 100, stdin); if (strcmp(message, "bye\n") == 0) break; if (send(sock, message, strlen(message), 0) < 0) { puts("Send failed"); return 1; } close(sock); return 0; } http://network.hanbat.ac.kr79
80
http://network.hanbat.ac.kr80 실습
81
FILE IO http://network.hanbat.ac.kr81
82
기본 내용 파일 하드디스크에 저장되어 있음 응용 프로세스 (process) 에서 바이트 단위로 입출력 파일에서 데이터를 읽고 쓸 때의 과정 파일을 열고 fopen 열린 파일의 데이터를 읽거나 쓰고 fscanf, fprintf 파일을 닫음 fclose 다 사용한 후에 82 HD HW OS (Kernel) APP.
83
File open FILE *fopen ( const char *filename, const char *mode ); filename 읽거나 쓸 파일의 이름 mode “r” 읽기 (read) 모드로 파일을 연다. 파일이 없으면 에러가 발생하고, NULL 값을 돌려준다. 파일이 있으면, marker 가 파일의 첫 부분을 가리킨다. marker: 다음에 읽을 위치 파일 오픈 후, 파일에 쓰려고 하면 에러 발생 “w” 쓰기 (write) 모드로 파일을 연다. 파일이 없으면 새로 만든다. 기존의 파일이 있으면 그 이전의 내용은 삭제된다. Marker 는 파일의 첫 부분을 가리킴. 파일 오픈 후, 파일에서 읽으려고 하면 에러 발생 “r+” 또는 “w+” : 읽거나 쓰기 용으로 open 83
84
“a” 추가 쓰기 (append) 모드로 파일을 연다. 파일이 없으면 새로 만든다. 기존의 파일이 있으면 marker 가 파일의 끝을 가리킨다 새로 추가되는 내용은 그 파일의 가장 뒤부터 파일에 추가한다. 파일 오픈 후, 파일에서 읽으려고 하면 에러 발생 Return 값 성공시 : FILE * 실패시 : NULL 예 : 없는 파일을 읽기 모드로 여는 경우 man fopen 예 #include FILE *fp; fp = fopen (“temp.dat”, “w”); 84
85
File close 파일에 대한 쓰기, 읽기 등의 작업이 종료된 후 int fclose ( FILE *fp ); fp 는 fopen () 이 리턴했던 파일 포인터 리턴값 0 은 성공적으로 닫았음을 나타냄 오류가 발생하면, 이 함수는 EOF 를 리턴 85
86
open/close 전체 예 #include int main (void) { FILE *fp; if ((fp=fopen("basic.txt", "w")) == NULL) { printf (“File open failed. \n"); } // write code... if (fclose(fp) == EOF) { printf("Error closing basic.txt\n"); } return 0; } 프로그램이 정상적으로 실행된 경우 basic.txt 파일이 생성됨 86
87
fprintf #include int main ( void ) { FILE *fp; if ((fp=fopen("basic.txt", "w")) == NULL) { printf ("The file (basic.txt) is not opened. \n"); } fprintf(fp, "My code name is %c, my code is %d.\n", 'Z', 123); if (fclose(fp) == EOF) { printf("Error closing basic.txt\n"); } return 0; } 87 실습
88
fscanf #include int main (void) { FILE *fp; char ch; int ret; if ((fp=fopen("basic.txt", "r")) == NULL) { printf ("The file ( basic.txt ) is not opened. \n"); } do { ret = fscanf (fp, "%c", &ch); // fscanf 는 읽은 항목 수를 리턴 if (ret == EOF)// file 의 끝까지 읽은 후에는 EOF 를 리턴 break; printf ("%c", ch); } while (1); if (fclose(fp) == EOF) { printf("Error closing basic.txt\n"); } return 0; } 88 실습
89
#include int main (void) { FILE *fp; char str[128]; int ret; if ((fp=fopen("basic.txt", "r")) == NULL) { printf ("The file ( basic.txt ) is not opened. \n"); } do { ret = fscanf (fp, "%s", str); if (ret == EOF) break; printf ("%s\n", str); } while (1); if (fclose(fp) == EOF) { printf("Error closing basic.txt\n"); } return 0; } 89
90
과제 간단한 파일전송 클라이언트 - 서버 (simple FTP) 클라이언트는 서버에게 자신이 원하는 파일 이름을 전송한다. 서버는 클라이언트로부터 수신한 파일이름의 파일 내용을 읽어서, 클라이언트에게 전송한다. 클라이언트는 서버로부터 수신되는 파일 내용을 자신의 하드디스크에 저장한다. 90
91
91 connection Client Server File data Save file contents Read file data Write file data File name “file name” 과제
92
IO BLOCKING http://network.hanbat.ac.kr92
93
문제점 서버가 n 개의 client 프로세스와 통신을 하는 경우 어느 클라이언트에서 데이터가 송신될지는 알 수 없는 경우 서버가 1 번 클라이언트에서 read 하면 1 번은 데이터를 송신하지 않은 경우 서버 blocking 3 번은 데이터를 송신하였음 서버가 이미 1 번 클라이언트로부터 데이터를 읽기 위해서 blocking 되었으므로, 읽혀지지 않음 1 번이 데이터를 보낼 때까지 서버는 blocking 해결방안 Non-blocking read Read loop, fcntl() with O_NONBLOCK select (2) http://network.hanbat.ac.kr93
94
select(2): I/O Multiplexing Waits on multiple file descriptors and timeout The select() system call allows us to use blocking I/O on a set of descriptors (file, socket, …). For example, we can ask select to notify us when data is available for reading on either STDIN or a TCP socket. Returns when any file descriptor is ready to be read or written or indicate an error, or timeout exceeded advantages simple application does not consume CPU cycles while waiting http://network.hanbat.ac.kr94
95
#include int select (int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout); maxfdp1 descriptors (0, 1,... maxfds-1) will be tested 보통 가장 큰 소켓번호에 1 을 더하여 사용 readset a set of fds we want to check if data is available returns a set of fds ready to read writeset returns a set of fds ready to write exceptset returns a set of fds with exception conditions http://network.hanbat.ac.kr95
96
Timeout if NULL, wait forever and return only when one of the descriptors is ready for I/O otherwise, wait up to a fixed amount of time specified by timeout if we don’t want to wait at all, create a timeout structure with timer value equal to 0 struct timeval { longtv_sec;/* seconds */ longtv_usec;/* microseconds */ }; /* 0.5 초 동안 sleep 하는 코드 */ struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 500000; /* 0.5 초 */ select(0, NULL, NULL, NULL, &timeval); http://network.hanbat.ac.kr96
97
반환값 성공시 감지된 소켓기술자의 수 타임아웃시 0 에러시 -1 http://network.hanbat.ac.kr97
98
fd_set 집합을 다루기 위해 사용되는 4 개의 매크로 http://network.hanbat.ac.kr98 매크로설명 void FD_ZERO (fd_set *fdset); fdset 의 모든 비트를 지운다. void FD_SET (int fd, fd_set *fdset) fdset 중 소켓 fd 에 해당하는 비트를 on(1) 시킨다 void FD_CLR (int fd, fd_set *fdset); fdset 중 소켓 fd 에 해당하는 비트를 off(0) 시킨다 int FD_ISSET (int fd, fd_set *fdset); fdset 중 소켓 fd 에 해당하는 비트가 on 되어 있으면 양수값을 반환한다
99
Pseudo code int s1, s2; /* socket descriptors */ fd_set readfds;/* used by select() */ /* create and bind s1 and s2 */ http://network.hanbat.ac.kr99
100
while(1) { FD_ZERO(&readfds);/* initialize the fd set */ FD_SET(s1, &readfds);/* add s1 to the fd set */ FD_SET(s2, &readfds);/* add s2 to the fd set */ if(select(s2+1, &readfds, 0, 0, 0) < 0) { perror(“select”); exit(1); } if(FD_ISSET(s1, &readfds)) { recvfrom(s1, buf, sizeof(buf),...); /* process buf */ } /* do the same for s2 */ } http://network.hanbat.ac.kr100
101
select 함수의 사용 예 select 함수를 사용한 TCP Concurrent echo 서버 - 클라이언트 http://network.hanbat.ac.kr101
102
echo_ser_tcp_select.c #include "inet.h" #include #define MSGLEN 1024 #define MAXCLI 50 int main(int argc, char *argv[]) { int sockfd, confd; struct sockaddr_in cliaddr, servaddr; int addrlen; fd_set read_fdset; http://network.hanbat.ac.kr102
103
int client_fd[MAXCLI]; int client_num = 0; char buf[MSGLEN]; int msg_len, maxfdp1, nready, i; pid_t childpid; if (argc != 2){ printf("Usage:echo_ser_select [Port number]\n"); exit(0); } if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("server: can't create socket\n"); exit(-1); } http://network.hanbat.ac.kr103
104
servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wild card */ servaddr.sin_port = htons(atoi(argv[1])); if ((bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0){ printf("server: bind error\n"); exit(-1); } listen(sockfd, 5); for (i=0; i<MAXCLI; i++) client_fd[i] = -1; FD_ZERO(&read_fdset); maxfdp1 = sockfd + 1; http://network.hanbat.ac.kr104
105
while(1) { FD_SET(sockfd, &read_fdset); for (i=0; i<MAXCLI; i++){ if (client_fd[i] != -1) FD_SET(client_fd[i], &read_fdset); } if ((nready=select(maxfdp1, &read_fdset, NULL, NULL, NULL) )< 0){ printf("select error..\n"); exit(-1); } http://network.hanbat.ac.kr105
106
if (FD_ISSET(sockfd, &read_fdset)){ addrlen = sizeof(cliaddr); confd=accept(sockfd,(struct sockaddr *)&cliaddr, &addrlen); if (confd < 0){ printf("server: accept error\n"); exit(-1); } if (client_num >= MAXCLI) { printf(“too many clients\n”); close(confd); continue; } printf("connection new client(confd=%d)...\n", confd); for (i=0; i<MAXCLI; i++) { if (client_fd[i] != -1) continue; client_fd[i] = confd;maxfdp1++; client_num++;break; } http://network.hanbat.ac.kr106
107
for ( i=0; i<MAXCLI; i++) { if (client_fd[i] == -1) continue; if (FD_ISSET(client_fd[i], &read_fdset)) { memset(buf, '\0', sizeof(buf)); msg_len = read(client_fd[i], buf, MSGLEN); if ( write(client_fd[i], buf, msg_len) != msg_len ) { printf("server: write error!!\n"); close(confd); exit(0); } if ( --nready <= 0) /* 더 이상 변화된 소켓기술자가 없다면 */ break; } } /* end of the 'while' */ } http://network.hanbat.ac.kr107
108
http://network.hanbat.ac.kr108 echo_cli_tcp_select.c #include "inet.h" #include #define MSGLEN 1024 int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in servaddr; fd_set read_fdset, reset; char buf[MSGLEN]; int len, msg_len, rcvlen, maxfdp1; if (argc != 3) { printf("Usage: echo_cli_select [Server IP] [Port number]\n"); exit(0); }
109
http://network.hanbat.ac.kr109 if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("client: can't create socket\n"); exit(-1); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(argv[1]); servaddr.sin_port = htons(atoi(argv[2])); if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){ printf("client: can't connect\n"); exit(-1); }
110
http://network.hanbat.ac.kr110 FD_ZERO(&read_fdset); FD_SET(0, &read_fdset); FD_SET(sockfd, &read_fdset); reset = read_fdset; maxfdp1 = sockfd + 1;
111
http://network.hanbat.ac.kr111 while(1){ read_fdset = reset; if (select(maxfdp1, &read_fdset, NULL, NULL, NULL) < 0) { printf("select error..\n"); exit(-1); } if (FD_ISSET(0, &read_fdset)){ memset(buf, '\0', sizeof(buf)); if ( (msg_len = read(0, buf, sizeof(buf))) <= 0) { close(sockfd);exit(0); } if ( write(sockfd, buf, msg_len) != msg_len ) { printf("client: write error!!\n"); close(sockfd); exit(0); }
112
http://network.hanbat.ac.kr112 if (FD_ISSET(sockfd, &read_fdset)) { memset(buf, '\0', sizeof(buf)); len=0; do { if ((rcvlen=read(sockfd,&buf[len],msg_len-len)) <= 0){ close(sockfd); exit(0); } len += rcvlen; } while(len < msg_len); printf("echo : %s", buf); }
113
http://network.hanbat.ac.kr113
114
UDP EXAMPLES http://network.hanbat.ac.kr114
115
UDP echo client/server http://network.hanbat.ac.kr115 Client Server echoed data Print Read from socket echo Read from KB data
116
UDP echo client/server udpEchoServer.c #include #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data void die (char *s) { perror(s); exit(1); } http://network.hanbat.ac.kr116
117
int main(void) { struct sockaddr_in si_me, si_other; int s, i, slen = sizeof(si_other), recv_len; char buf[BUFLEN]; if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { die("socket"); } memset((char *) &si_me, 0, sizeof(si_me)); si_me.sin_family = AF_INET; si_me.sin_port = htons(PORT); si_me.sin_addr.s_addr = htonl(INADDR_ANY); if( bind(s, (struct sockaddr*)&si_me, sizeof(si_me) ) == -1) { die("bind"); } http://network.hanbat.ac.kr117
118
while(1) { printf("Waiting for data..."); fflush(stdout); //try to receive some data, this is a blocking call if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1) { die("recvfrom()"); } buf[recv_len] = 0;// set null char. //print details of the client/peer and the data received printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n", buf); http://network.hanbat.ac.kr118
119
//now reply the client with the same data if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == -1) { die("sendto()"); } }// while close(s); return 0; } http://network.hanbat.ac.kr119
120
udpEchoClient.c #include #define SERVER "127.0.0.1" #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to send data void die(char *s) { perror(s); exit(1); } http://network.hanbat.ac.kr120
121
main(void) { struct sockaddr_in si_other;int s, i, slen=sizeof(si_other); char buf[BUFLEN];char message[BUFLEN]; if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { die("socket"); } memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); if (inet_aton(SERVER, &si_other.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(1); } http://network.hanbat.ac.kr121
122
while(1) { printf("Enter message : ");fgets(message, 512, stdin); if (sendto(s, message, strlen(message), 0, (struct sockaddr *) &si_other, slen)==-1) { die("sendto()"); } //clear the buffer by filling null, it might have previously received data memset(buf, '\0', BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) { die("recvfrom()"); } puts(buf); } http://network.hanbat.ac.kr122
123
close(s); return 0; } http://network.hanbat.ac.kr123
124
http://network.hanbat.ac.kr124 실습
125
Iterative echo 서버와 클라이언트 http://network.hanbat.ac.kr125
126
http://network.hanbat.ac.kr126 echo_ser_iter_udp.c #include "inet.h" #define MSGLEN 128 int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in servaddr, cliaddr; int addrlen, msg_len; char clidot[20], buf[MSGLEN]; time_t date; if (argc != 2){ printf("Usage: echo_ser_iter_udp [Port number]\n"); exit(0); }
127
http://network.hanbat.ac.kr127 if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ printf("server: can't create socket\n"); exit(-1); } servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wild card */ servaddr.sin_port = htons(atoi(argv[1])); if ( (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0){ printf("server: bind error\n"); exit(-1); }
128
http://network.hanbat.ac.kr128 while(1) { memset(buf, '\0', sizeof(buf)); addrlen = sizeof(cliaddr); msg_len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &addrlen); if (msg_len < 0) continue; printf("client: %s, port %d message length: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, clidot, sizeof(clidot)), ntohs(cliaddr.sin_port), msg_len); if (sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr))!= msg_len) printf("sendto error\n"); }
129
http://network.hanbat.ac.kr129 echo_cli_udp.c #include "inet.h" #include #define MSGLEN 128 int main(int argc, char *argv[]) { int sockfd, clifd;struct sockaddr_in servaddr; fd_set read_fdset, reset; int addrlen, len, msg_len, maxfdp1; char buf[MSGLEN]; time_t date; if (argc != 3){ printf("Usage: echo_cli_dup [Server IP] [Port number]\n"); exit(0); }
130
http://network.hanbat.ac.kr130 if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ printf("client: can't create socket\n"); exit(-1); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(argv[1]); servaddr.sin_port = htons(atoi(argv[2])); FD_ZERO(&read_fdset); FD_SET(0, &read_fdset); FD_SET(sockfd, &read_fdset); reset = read_fdset; maxfdp1 = sockfd + 1;
131
http://network.hanbat.ac.kr131 while(1){ read_fdset = reset; if (select(maxfdp1, &read_fdset, NULL, NULL, NULL) < 0){ printf("select error..\n"); exit(-1); }
132
http://network.hanbat.ac.kr132 if (FD_ISSET(0, &read_fdset)){ memset(buf, '\0', sizeof(buf)); if ( (msg_len = read(0, buf, sizeof(buf))) <= 0){ close(sockfd); exit(0); } if (sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) != msg_len){ printf("sendto error\n"); close(sockfd); exit(-1); }
133
http://network.hanbat.ac.kr133 if (FD_ISSET(sockfd, &read_fdset)){ memset(buf, '\0', sizeof(buf)); addrlen = sizeof(servaddr); len = recvfrom(sockfd, buf, MSGLEN, 0,(struct sockaddr *) &servaddr, &addrlen); printf("echo : %s", buf); } } /* end of the ‘while’ */ }
134
http://network.hanbat.ac.kr134
135
Concurrent echo 서버 http://network.hanbat.ac.kr135
136
http://network.hanbat.ac.kr136 echo_ser_con_udp.c #include "inet.h" #define MSGLEN 128 int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in servaddr, cliaddr; int addrlen, msg_len; char clidot[20], buf[MSGLEN]; time_t date; if (argc != 2) { printf("Usage: echo_ser_iter_udp [Port number]\n"); exit(0); }
137
http://network.hanbat.ac.kr137 if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ printf("server: can't create socket\n"); exit(-1); } servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wild card */ servaddr.sin_port = htons(atoi(argv[1])); if ( (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0){ printf("server: bind error\n"); exit(-1); }
138
http://network.hanbat.ac.kr138 while(1) { memset(buf, '\0', sizeof(buf)); addrlen = sizeof(cliaddr); msg_len = recvfrom (sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &addrlen); if (msg_len < 0) continue; if (fork() == 0){ printf("client: %s, port %d message length: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, clidot, sizeof(clidot)), ntohs(cliaddr.sin_port), msg_len); if (sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr))!= msg_len) printf("sendto error\n"); return 0; } /* end of the ‘child’ */ } /* end of the 'while' */ }
139
http://network.hanbat.ac.kr139
Similar presentations