1 소켓
2 1 소켓
클라이언트 - 서버모델 네트워크응용프로그램 클리이언트 - 서버모델을기반으로동작한다. 클라이언트 - 서버모델 하나의서버프로세스와여러개의클라이언트로구성된다. 서버는어떤자원을관리하고클라이언트를위해자원관련서비스를제공한다. 3
소켓의종류 소켓 네트워크에대한사용자수준의인터페이스를제공 소켓은양방향통신방법으로클라이언트 - 서버모델을기반으로프로세스사이의통신에매우적합하다. 유닉스소켓 (AF_UNIX) 같은호스트내의프로세스사이의통신방법 인터넷소켓 (AF_INET) 인터넷에연결된서로다른호스트에있는프로세스사이의통신방법 4
소켓연결 1. 서버가소켓을만든다. 2. 클라이언트가소켓을만든후서버에연결요청을한다. 3. 서버가클라이언트의연결요청을수락하여소켓연결이이루어진다. 5
소켓연결과정 서버 1. socket() 호출을이용하여소켓을만들고이름을붙인다. 클라이언트 1. socket() 호출을이용하여소켓을만든다. 2. listen() 호출을이용하여대기큐를만든다. 2. connection() 호출을이용하여서버에연결요청을한다. 3. 클라이언트로부터연결요청을 accept() 호출을이용하여수락 3. 서버가연결요청을수락하면소켓연결이만들어진다. 4. 소켓연결이이루어지면 - 자식프로세스를생성하여 - 클라이언트로부터요청처리 - 클라이언트에게응답한다. 4. 서버에서비스를요청하고 서버로부터응답을받아처리 6
소켓연결과정 7
소켓만들기 int socket(int domain, int type, int protocol) 소켓을생성하고소켓을위한파일디스크립터를리턴, 실패하면 -1 을리턴 인터넷소켓 fd = socket(af_inet, SOCK_STREAM, DEFAULT _PROTOCOL); 유닉스소켓 fd = socket(af_unix, SOCK_STREAM, DEFAULT _PROTOCOL); 8
소켓에이름 ( 주소 ) 주기 int bind(int fd, struct sockaddr* address, int addresslen) 소켓에대한이름바인딩이성공하면 0 을실패하면 -1 을리턴한다. 유닉스소켓이름 struct sockaddr_un { } unsigned short sun_family; char sun_path[108]; 인터넷소켓이름 9 } struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; // AF_UNIX // 소켓이름 // AF_INET // 인터넷소켓의포트번호 // 32-bit IP 주소 // 사용안함
소켓큐생성 listen() 시스템호출 클라이언트로부터의연결요청을기다린다. 연결요청대기큐의길이를정한다. int listen(int fd, int queuelength) 소켓 fd 에대한연결요청을기다린다. 성공하면 0 을실패하면 -1 을리턴 listen(serverfd, 5); 10
소켓에연결요청 connect() 시스템호출 fd 가나타내는클라이언트소켓과 address 가나타내는서버소켓과의연결을요청한다. 성공하면 fd 를서버소켓과의통신에사용할수있다. int connect(int fd, struct sockaddr* address, int addresslen) 성공하면 0 을실패하면 -1 를리턴한다. 11
연결요청수락 int accept(int fd, struct sockaddr* address, int* addresslen) 성공하면새로만들어진복사본소켓의파일디스크립터, 실패하면 -1 을리턴 서버가클라이언트로부터의연결요청을수락하는내부과정 1. 서버는 fd가나타내는서버소켓을경청하고 2. 클라이언트의연결요청이올때까지기다린다. 3. 클라이언트로부터연결요청이오면원래서버소켓과같은복사본소켓을만들어이복사본소켓과클라이언트소켓을연결 4. 연결이이루어지면 address는클라이언트소켓의주소로세팅되고 addresslen는그크기로세팅 5. 새로만들어진복사본소켓의파일디스크립터를리턴 12
대문자변환서버 이프로그램 입력받은문자열을소문자를대문자로변환한다. 서버와클라이언트로구성된다. 서버 소켓을통해클라이언트로부터받은문자열을소문자를대문자로변환하여소켓을통해클라이언트에다시보낸다. 클라이언트 표준입력으로부터문자열을입력받아 이를소켓을통해서버에보낸후에 대문자로변환된문자열을다시받아표준출력에출력 13
cserver.c 1 #include <stdio.h> 2 #include <signal.h> 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <sys/un.h> 6 #define DEFAULT_PROTOCOL 0 7 #define MAXLINE 100 9 /* 소문자를대문자로변환하는서버프로그램 */ 10 int main () 11 { 12 int listenfd, connfd, clientlen; 13 char inmsg[maxline], outmsg[maxline]; 14 struct sockaddr_un serverunixaddr, clientunixaddr; 15 16 signal(sigchld, SIG_IGN); 17 clientlen = sizeof(clientunixaddr); 18 19 listenfd = socket(af_unix, SOCK_STREAM, DEFAULT_PROTOCOL); 20 serverunixaddr.sun_family = AF_UNIX; 14
cserver.c 21 strcpy(serverunixaddr.sun_path, "convert"); 22 unlink("convert"); 23 bind(listenfd, &serverunixaddr, sizeof(serverunixaddr)); 24 25 listen(listenfd, 5); 26 27 while (1) { /* 소켓연결요청수락 */ 28 connfd = accept(listenfd, &clientunixaddr, &clientlen); 29 if (fork ( ) == 0) { 30 /* 소켓으로부터한줄을읽어대문자로변환하여보냄 */ 31 readline(connfd, inmsg); 32 toupper(inmsg, outmsg); 33 write(connfd, outmsg, strlen(outmsg)+1); 34 close(connfd); 35 exit (0); 36 } else close(connfd); 37 } 38 } 15
cserver.c 40 /* 소문자를대문자로변환 */ 41 toupper(char* in, char* out) 42 { 43 int i; 44 for (i = 0; i < strlen(in); i++) 45 if (islower(in[i])) 46 out[i] = toupper(in[i]); 47 else out[i] = in[i]; 48 out[i] = NULL; 49 } 50 51 /* 한줄읽기 */ 52 readline(int fd, char* str) 53 { 54 int n; 55 do { 56 n = read(fd, str, 1); 57 } while(n > 0 && *str++!= NULL); 58 return(n > 0); 5916 }
cclient.c 1 #include <stdio.h> 2 #include <signal.h> 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <sys/un.h> 6 #define DEFAULT_PROTOCOL 0 7 #define MAXLINE 100 8 9 /* 소문자 - 대문자변환 : 클라이언트프로그램 */ 10 int main ( ) 11 { 12 int clientfd, result; 13 char inmsg[maxline], outmsg[maxline]; 14 struct sockaddr_un serverunixaddr; 15 16 clientfd = socket(af_unix, SOCK_STREAM, DEFAULT_PROTOCOL); 17 serverunixaddr.sun_family = AF_UNIX; 18 strcpy(serverunixaddr.sun_path, "convert"); 17
cclient.c 20 do { /* 연결요청 */ 21 result = connect(clientfd, &serverunixaddr, sizeof(serverunixaddr)); 22 if (result == -1) sleep(1); 23 } while (result == -1); 24 25 printf(" 변환할문자열입력 :\n"); 26 fgets(inmsg, MAXLINE, stdin); 27 write(clientfd,inmsg,strlen(inmsg)+1); // 변환할문자열보내기 28 29 /* 소켓으로부터변환된문자열을한줄읽어서프린트 */ 30 readline(clientfd,outmsg); 31 printf("%s --> \n%s", inmsg, outmsg); 32 close(clientfd); 33 exit(0); 34 } 18
fclient.c 38 do { /* 연결요청 */ 39 result = connect(clientfd, &serveraddr, sizeof(serveraddr)); 40 if (result == -1) sleep(1); 41 } while (result == -1); 42 43 printf(" 파일이름입력 :"); 44 scanf("%s", inmsg); 45 write(clientfd,inmsg,strlen(inmsg)+1); 46 47 /* 소켓으로부터파일내용읽어서프린트 */ 48 while (readline(clientfd,outmsg)) 49 printf("%s", outmsg); 50 close(clientfd); 51 exit(0); 52 } 19
핵심개념 소켓은양방향통신방법으로클라이언트 - 서버모델을기반으로프로세스사이의통신에매우적합하다. 소켓에는같은호스트내의프로세스사이의통신을위한유닉스소켓과다른호스트에있는프로세스사이의통신을위한인터넷소켓이있다. 20