400 likes | 420 Views
제 14 장 소켓 통신. 목표. network programming with socket. Socket. Sockets. Socket bidirectional connection process communication based on client-server model AF_UNIX socket an interprocess communication mechanism between processes on the same UNIX machine AF_INET socket
E N D
목표 • network programming with socket
Sockets • Socket • bidirectional connection • process communication based on client-server model • AF_UNIX socket • an interprocess communication mechanism between processes on the same UNIX machine • AF_INET socket • an interprocess communication mechanism between processes across network
A Client-Server Transaction • Every network application is based on the client-server model: • A server process and one or more clientprocesses • Server manages some resource. • Server providesservice by manipulating resource for clients. 1. Client sends request Client process Server process Resource 4. Client handles response 2. Server handles request 3. Server sends response Note: clients and servers are processes running on hosts (can be the same or different hosts).
Server Server Client Server Client Socket connection 1. Sever creates a named socket 2. Client creates an unnamed socket and request a connection 3. Server accepts a connection. Server retains original named socket
Client-Server Model • Server • Server creates a named socket using socket() • Server makes a peding queue using listen() • Server accept()from a client connection() • When a socket isconnected the server usually fork()a child process to converse with the client • Client • Client creates an unnamed socket using socket() • Client requests a connection using connect() • Client makes a connection when server accept( ) it.
클라이언트 서버 socket socket bind listen 연결 요청 connect accept 서비스 요청 서비스 요청 처리 다음 클라이언트로부터 연결 요청을 기다림 응답 처리 서비스 응답 EOF close close
Creating a Socket • 소켓 만들기 • int socket(int domain, int type, int protocol) • domain • AF_UNIX • AF_INET • type • SOCK_STREAM • protocol • DEFAULT _PROTOCOL • Example fd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL);
Naming a Socket • 소켓에 이름(주소) 주기 • int bind(int fd, struct sockaddr* address, int addressLen) • bind the unnamed socket with fd to a name in address • address is a pointer to struct sockaddr_un sun_family = AF_UNIX sun_path = name of the socket struct sockaddr_in sin_family = AF_INET sin_port = the port number of Internet socket sin_addr = 32-bit IP address sin_zero = leave empty • addressLen = length of address structure
Example serverUNIXAddress.sun_family = AF_UNIX; strcpy(serverUNIXAddress.sun_path, “convert”); unlink(“convert”); bind(fd, &serverUNIXAddress, serverLen);
Creating a Socket Queue • 소켓 큐 생성 • int listen(int fd, int queueLength) • specify the maximum number of pending connections on a socket • example listen(serverFd, 5);
Making the Connection • 소켓에 연결 요청 • int connect(int fd, struct sockaddr* address, int addressLen) • attempts to connect to a server socket whose address is in a structure pointed to by address • If successful, fd may be used to communicate with the server’s socket
Accepting a Client • 소켓 연결 요청 수락 • int accept(int fd, struct sockaddr* address, int* addressLen) (1) listen to the named server socket referenced by fd (2)wait until a client connection request is received (3) creates an unnamed socket with the same attributes as the original server socket, and connects it to the client’s socket. (4) When a connection is made, address is set to the address of the client socket and addressLen is set to the actual size (5) return a new file descriptor
Convert Server/Client • 이 프로그램은 입력 받은 문자열을 소문자를 대문자로 변환한다. • 서버 • 소켓을 통해 클라이언트로부터 받은 문자열을 • 소문자를 대문자로 변환하여 • 소켓을 통해 클라이언트에 다시 보낸다. • 클라이언트 • 표준입력으로부터 문자열을 입력 받아 • 이를 소켓을 통해 서버에 보낸 후에 • 소켓을 통해 대문자로 변환된 문자열을 다시 받아 • 표준출력에 출력한다.
Convert Server(1/3) #include <stdio.h>#include <signal.h> #include <sys/types.h>#include <sys/socket.h> #include <sys/un.h> #define DEFAULT_PROTOCOL 0 #define MAXLINE 100 main ( ){ int listenfd, connfd, clientlen; char inmsg[MAXLINE], outmsg[MAXLINE]; struct sockaddr_un serverUNIXaddr, clientUNIXaddr; signal(SIGCHLD, SIG_IGN); clientlen = sizeof(clientUNIXaddr); listenfd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL); serverUNIXaddr.sun_family = AF_UNIX; strcpy(serverUNIXaddr.sun_path, "convert");
Convert Server(2/3) unlink("convert"); bind(listenfd, &serverUNIXaddr, sizeof(serverUNIXaddr)); listen(listenfd, 5); while (1) { connfd = accept(listenfd, &clientUNIXaddr, &clientlen); if (fork ( ) == 0) { readLine(connfd, inmsg); toUpper(inmsg, outmsg); write(connfd, outmsg, strlen(outmsg)+1); close(connfd); exit (0); } else close(connfd); } }
Convert Server(3/3) toUpper(char* in, char* out) { int i; for (i = 0; i < strlen(in); i++) if (islower(in[i])) out[i] = toupper(in[i]); else out[i] = in[i]; out[i] = NULL; }
Convert Client(1/2) #include <stdio.h>#include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define DEFAULT_PROTOCOL 0 #define MAXLINE 100 main ( ) { int clientfd, serverLen, result; char inmsg[MAXLINE], outmsg[MAXLINE]; struct sockaddr_un serverUNIXaddr; clientfd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL); serverUNIXaddr.sun_family = AF_UNIX; strcpy(serverUNIXaddr.sun_path, "convert");
Convert Client(2/2) do { result = connect(clientfd, &serverUNIXaddr,sizeof(serverUNIXaddr)); if (result == -1) sleep(1); } while (result == -1); fgets(inmsg, MAXLINE, stdin); write(clientfd,inmsg,strlen(inmsg)+1); readLine(clientfd,outmsg); printf("%s --> \n%s", inmsg, outmsg); close(clientfd); exit(0); } 20
Internet Sockets • Internet socket is specified by two values: a 32-bit IP address a 16-bit port number, which specifies a particular port on the host struct sockaddr_in sin_family = AF_INET sin_port = 16bit port number of the Internet socket sin_addr = 32-bit IP address , which is a structure of type in_addr sin_zero = leave empty
Socket Address Structures • Generic socket address: • For address arguments to connect, bind, and accept. • Necessary only because C did not have generic (void *) pointers when the sockets interface was designed. • Internet-specific socket address: • Must cast (sockaddr_in *) to (sockaddr *) for connect, bind, and accept. struct sockaddr { unsigned short sa_family; /* protocol family */ char sa_data[14]; /* address data. */ }; structsockaddr_in { unsigned short sin_family; /* address family (always AF_INET) */ unsigned short sin_port; /* port num in network byte order */ structin_addrsin_addr; /* IP addr in network byte order */ unsigned char sin_zero[8]; /* pad to sizeof(structsockaddr) */ };
A Programmer’s View of the Internet • 1. Hosts are mapped to a set of 32-bit IP addresses. • 128.2.203.179 • 2. IP addresses is mapped to a domain name. • 128.2.203.179 is mapped to www.cs.cmu.edu • 3. A process on one Internet host can communicate with a process on another Internet host over a connection.
IP Addresses • 32-bit IP addresses are stored in an IP address struct • IP addresses are always stored in memory in network byte order • True in general for any integer transferred in a packet header from one machine to another. • E.g., the port number used to identify an Internet connection. /* Internet address structure */ structin_addr { unsigned ints_addr; /* network byte order (big-endian) */ }; • Handy network byte-order conversion functions: • htonl: convert long int from host to network byte order. • htons: convert short int from host to network byte order. • ntohl:convert long int from network to host byte order. • ntohs: convert short int from network to host byte order.
Domain Naming System (DNS) • The Internet maintains a mapping between IP addresses and domain names in a huge worldwide distributed database called DNS. • Conceptually, programmers can view the DNS database as a collection of millions of host entry structures: /* DNS host entry structure */ structhostent { char *h_name; /* official domain name of host */ char **h_aliases; /* null-terminated array of domain names */ inth_addrtype; /* host address type (AF_INET) */ inth_length; /* length of an address, in bytes */ char **h_addr_list; /* null-terminated array of in_addrstructs */ };
Functions for DNS #include <netdb.h> #include <sys/socket.h> /* for AF_INET */ struct hostent* gethostbyname(char* name) struct hostent *gethostbyaddr(const char *addr, int len, int type); • searches the “/etc/hosts” file and returns a pointer to a hostent structure that describes the file entry associated with the string name
Internet Connections • Clients and servers communicate by sending streams of bytes over connections. • Connections are point-to-point, full-duplex (2-way communication), and reliable. Client socket address 128.2.194.242:51213 Server socket address 208.216.181.15:80 Client Server (port 80) Connection socket pair (128.2.194.242:51213, 208.216.181.15:80) Client host address 128.2.194.242 Server host address 208.216.181.15 Note: 80 is a well-known port associated with Web servers Note: 51213 is an ephemeral port allocated by the kernel
Clients • Examples of client programs • Web browsers, ftp, telnet, ssh • How does a client find the server? • The IP address in the server socket address identifies the host • The (well-known) port in the server socket address identifies the service • Examples of well know ports • Port 7: Echo server • Port 23: Telnet server • Port 25: Mail server • Port 80: Web server
Using Ports to Identify Services Server host 128.2.194.242 Client host Web server (port 80) Service request for 128.2.194.242:80 (i.e., the Web server) Kernel Client Echo server (port 7) Web server (port 80) Service request for 128.2.194.242:7 (i.e., the echo server) Kernel Client Echo server (port 7)
Servers • Servers are long-running processes (daemons). • Created at boot-time (typically) by the init process (process 1) • Run continuously until the machine is turned off. • Each server waits for requests to arrive on a well-known port associated with a particular service. • Port 7: echo server • Port 23: telnet server • Port 25: mail server • Port 80: HTTP server • A machine that runs a server process is also often referred to as a “server.”
Server Examples • Web server (port 80) • Resource: files/compute cycles (CGI programs) • Service: retrieves files and runs CGI programs on behalf of the client • FTP server (20, 21) • Resource: files • Service: stores and retrieve files • Telnet server (23) • Resource: terminal • Service: proxies a terminal on the server machine • Mail server (25) • Resource: email “spool” file • Service: stores mail messages in spool file See /etc/services for a list of the services available on a Linux machine.
File Server/Client • 클라이언트가 파일을 요청하면 서버가 그 파일 내용을 보내준다. • 서버 • 소켓을 통해 클라이언트로부터 받은 파일 이름을 이용하여 • 해당 파일을 연 후 그 내용을 읽어 • 소켓을 통해 클라이언트에 다시 보낸다. • 클라이언트 • 표준입력으로부터 파일 이름을 입력 받아 • 이를 소켓을 통해 서버에 보낸 후에 • 소켓을 통해 파일 내용을 다시 받아 • 표준출력에 출력한다.
File Client(1/3) #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define DEFAULT_PROTOCOL 0 #define MAXLINE 100 main (int argc, char* argv[]) { int clientFd, port, result; char *host, inmsg[MAXLINE], outmsg[MAXLINE]; struct sockaddr_in serverAddr; struct hostent *hp; if (argc != 3) { fprintf(stderr, "사용법 : %s <host> <port>\n", argv[0]); exit(0); }
File Client(2/3) host = argv[1]; port = atoi(argv[2]); clientFd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL); // 서버의 IP 주소와 포트 번호를 채운다. if ((hp = gethostbyname(host)) == NULL) perror("gethostbyname error"); // 호스트 찾기 오류 bzero((char *) &serverAddr, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; bcopy((char *)hp->h_addr_list[0], (char *)&serverAddr.sin_addr.s_addr, hp->h_length); serverAddr.sin_port = htons(port); do { result = connect(clientFd, &serverAddr, sizeof(serverAddr)); if (result == -1) sleep(1); } while (result == -1);
File Client(3/3) printf("파일 이름 입력:"); scanf("%s", inmsg); write(clientFd,inmsg,strlen(inmsg)+1); while (readLine(clientFd,outmsg)) printf("%s", outmsg); close(clientFd); exit(0); } readLine(int fd, char* str) { int n; do { n = read(fd, str, 1); } while (n > 0 && *str++ != NULL); return(n > 0); }
Miscellaneous system calls • unsigned long inet_addr(char* string) • returns the 32-bit IP address that corresponds to the A.B.C.D format string • char* inet_ntoa(struct in_addr address) • returns a pointer to a string that describes address in the format A.B.C.D.
File Server(1/3) #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define DEFAULT_PROTOCOL 0 #define MAXLINE 100 main (int argc, char* argv[]) { int listenfd, connfd, port, clientlen; FILE *fp; char inmsg[MAXLINE], outmsg[MAXLINE]; struct sockaddr_in serveraddr, clientaddr; struct hostent *hp; char *haddrp; signal(SIGCHLD, SIG_IGN); if (argc != 2) { fprintf(stderr, "사용법: %s <port>\n", argv[0]); exit(0); }
File Server(2/3) port = atoi(argv[1]); listenfd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL); bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons((unsigned short)port); bind(listenfd, &serveraddr, sizeof(serveraddr)); listen(listenfd, 5); while (1) { clientlen = sizeof(clientaddr); connfd = accept(listenfd, &clientaddr, &clientlen); // 클라이언트의 도메인 이름과 IP 주소 결정 hp = gethostbyaddr((char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET); haddrp = inet_ntoa(clientaddr.sin_addr); printf("서버: %s (%s) %d에 연결됨\n", hp->h_name, haddrp, clientaddr.sin_port);
File Server(3/3) if (fork ( ) == 0) { readLine(connfd, inmsg); fp = fopen(inmsg, "r"); if (fp == NULL) { write(connfd, "해당 파일 없음", 10); } else { while(fgets(outmsg, MAXLINE, fp) != NULL) write(connfd, outmsg, strlen(outmsg)+1); } close(connfd); exit (0); } else close(connfd); } }