Download presentation
Presentation is loading. Please wait.
Published byΣάπφιρα Λούπης Modified 6년 전
1
인터넷에서의 데이터 흐름 Application Transport Transport Network Link Unix
도착주소(IP) 전달 세그먼트 분할+포장+도착주소 중간주소 붙여 포장(도착주소 or라우터주소) 중간주소를 local network 주소로 변환 포장 벗겨 도착주소 확인 후 아니면 다시 포장+새중간주소(옆의 다른 라우터 주소) 메시지 재구성 포장 벗겨 도착주소 확인 맞으면 위로 전달 포장 벗겨 위로 전달 Transport 포장 벗겨 위로 전달 Unix
2
연결형 소켓 시스템 호출 Server(connection oriented protocol) Client
blocks until connection from client connection establishment data(request) process request data(reply) socket() bind() listen() accept() socket() connect() read() write() write() read() Unix
3
비연결형 소켓 시스템 호출 Client blocks until data received from a client
Server(connectionless protocol) Client blocks until data received from a client data(request) process request data(reply) socket() bind() recvfrom() socket() bind() sendto() write() read() Unix
4
소켓의 종류 소켓 : 존재하는 프로세스들 사이의 대화를 가능하게 하는 프로세스간 상호 통신 방식 소켓의 종류
유형 : 클라이언트와 서버 사이에 존재할 수 있는 통신의 유형을 결정한다. SOCK_STREAM : 일련 번호가 붙은, 신뢰적, 양방향 연결에 기초한 바이트의 가변 길이의 스트림 SOCK_DGRAM : 전보와 비슷한, 무연결, 비신뢰적 고정 길이의 메시지 SOCK_SEQPACKET(몇몇 도메인에서만 구현됨) : 일련 번호가 붙은, 신뢰적, 양방향 연결에 기초한 바이트의 고정길이 패킷 SOCK_RAW (몇몇 도메인에서만 구현됨) :내부 네트워크 프로토콜과 인터페이스에 대한 접근을 제공 프로토콜 프로토콜의 매개 변수를 요구하는 시스템 호출은 0을 “올바른 프로토콜”을 의미한다고 받아들인다. 즉, 그 프로토콜 값은 일반적으로 신경 쓸 필요가 없는 것이다. 대부분의 시스템은 단지 선택적인 여분으로서 0 이외의 프로토콜을 제공한다. 소켓 : 존재하는 프로세스들 사이의 대화를 가능하게 하는 프로세스간 상호 통신 방식 소켓의 종류 다음 3개의 속성들에 따라 분류된다. 도메인 :서버와 클라이언트 소켓이 존재하는 장소를 가리킨다. AF_UNIX : 클라이언트와 서버는 동일한 기계에 존재해야 한다. AF_INET: 클라이언트와 서버는 인터네트 어느 곳에든지 존재할 수 있다. AF_NS :클라이언트와 서버는 XEROX네트워크 시스템에 존재할 수 있다. AF (Address Family)의 약자이다. 이와 유사한 PF(Protocol Family)로 시작하는 상수의 집합(예를 들면 PF_UNIX, PF_INET등)이 있다. AF와 PF는 동등하기 때문에 어느것을 사용해도 무방하다 Unix
5
소켓 프로그램 작성. 반드시 “/usr/include/sys/type.h” 와
”/usr/include/sys/socket.h”를 포함해야 한다. 서버는 다음 시스템 호출 순서대로 사용 Unix
6
소켓 프로그램 작성.. int socket(int domain, int type, int protocol)
성공하면 새로 생성된 소켓에 연관된 파일 기술자를 반환 실패하면 -1을 반환 int accept(int fd, struct sockaddr* address, int* addressLen) fd에 의해 참조되는 서버 소켓에 listen()을 실행 요구가 있으면 원래의 명명된 서버 소켓과 동일한 속성을 갖는 소켓을 생성하고, 그것을 클라이언트의 소켓에 연결한 다음 새로운 파일 기술자를 반환하고 원래의 명명된 서버 소켓은 다른 연결을 받아들이기 위해서 사용된다. 서버에서 연결이 성공할 때 다음과 같은 과정을 수행 서버 프로세스는 fork()를 수행 부모 프로세스는 새로 형성된 클라이언트 파일 기술자를 닫고, accept()로 되돌아가 새로운 클라이언트의 요구를 서비스할 준비 자식 프로세스는 read()와 write()를 통해 클라이언트와 대화 Unix
7
소켓 프로그램 작성... 클라이언트는 명명되지 않은 소켓을 생성하고 그 소켓을 명명된 서버 소켓에 접속시키는 것을 책임지는 프로세스 시스템 호출을 제시된 순서대로 사용 클라이언트에서 소켓 연결하기 int connect(int fd, struct sockaddr* address, int addressLen) address에 의해 포인트되는 구조체 내에 주소가 저장되어 있는 서버 소켓에 연결을 시도 성공하면 fd는 서버의 소켓과 통신하기 위해서 사용됨 addressLen은 주소 구조체의 크기와 동일해야 한다. Unix
8
Chef.c : 서버. #include <stdio.h> #include <signal.h>
#include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> /* AF_UNIX 소켓용 */ #define DEFAULT_PROTOCOL 0 main() { int serverFd, clientFd, serverLen, clientLen; struct sockaddr_un serverUNIXAddress; /* 서버 주소 */ struct sockaddr_un clientUNIXAddress; /* 클라이언트 주소 */ struct sockaddr* serverSockAddrPtr; /* 서버 주소에 대한 포인터 */ struct sockaddr* clientSockAddrPtr; /* 클라이언트 주소에 대한 포인터 */ /* 좀비(zombie)를 방지하기 위해 자식-죽음 시그널은 무시 */ signal(SIGCHLD, SIG_IGN); serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress; serverLen = sizeof(serverUNIXAddress); clientSockAddrPtr = (struct sockaddr*) &clientUNIXAddress; clientLen = sizeof(clientUNIXAddress); Unix
9
Chef.c : 서버.. /* 양방향, 디폴트 프로토콜의 유닉스 소켓 생성 */
serverFd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL); serverUNIXAddress.sun_family = AF_UNIX; /* 도메인 유형 설정 */ strcpy (serverUNIXAddress.sun_path, "recipe"); /* 이름 설정*/ unlink( "recipe"); /* 이미 존재 한다면, 파일 제거 */ bind(serverFd, serverSockAddrPtr, serverLen); /* 파일 생성 */ listen(serverFd, 5); /* 대기중인 연결의 최대 길이 */ while(1) /* 무한루프 */ { /* 클라이언트 연결 받기 */ clientFd = accept(serverFd, clientSockAddrPtr, &clientLen); printf(" Server called! "); if (fork() == 0) { /* 조리법을 전송할 자식 생성 */ writeRecipe(clientFd); /* 조리법 전송 */ close(clientFd); /* 소켓 닫기 */ exit(/* EXIT_SUCCESS */ 0); /* 종료 */ } else close(clientFd); /* 클라이언트 기술자 닫기 */ } writeRecipe (int fd) { static char* line1 = "spam, spam, spam, spam, spam,"; static char* line2 = "spam, and spam."; write (fd, line1, strlen(line1) + 1); /* 첫째줄 쓰기 */ write (fd, line2, strlen(line2) + 1); /* 두번째 줄 쓰기 */ Unix
10
Cook.c : 클라이언트. #include <stdio.h> #include <signal.h>
#include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define DEFAULT_PROTOCOL 0 main() { int clientFd, serverLen, result; struct sockaddr_un serverUNIXAddress; struct sockaddr* serverSockAddrPtr; serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress; serverLen = sizeof(serverUNIXAddress); /* 양방향, 디폴트 프로토콜의유닉스 소켓생성 */ clientFd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL); serverUNIXAddress.sun_family = AF_UNIX; /* 서버 도메인 */ strcpy( serverUNIXAddress.sun_path, "recipe"); /* 서버 이름 */ Unix
11
Cook.c : 클라이언트.. do { /* 서버와 연결되기까지 루프 */
result = connect (clientFd, serverSockAddrPtr, serverLen); if(result == -1) sleep(1); /* 대기후 다시 시도 */ } while(result == -1); readRecipe(clientFd); /* 조리법 읽기 */ close(clientFd); /* 소켓 닫기 */ exit(/* EXIT_SUCCESS */ 0); /* 수행 끝*/ } readRecipe(int fd) { char str[200]; while(readLine(fd, str)) /* 입력 끝까지 줄 읽기 */ printf("%s\n", str); /* 소켓으로부터 줄 출력 */ readLine(int fd, char* str) int n; do { n = read(fd,str,1); while(n > 0 && *str++ != NULL); return (n > 0); Unix
12
인터넷 소켓 프로그램 API struct sockaddr_in
sin_family : 소켓 도메인 sin_port : 포트 번호 sin_addr : 32 비트 IP 번호 (INADDR_ANY: 어떤 호스트의 클라이언트도 다 받아들임) sin_zero : 삽입구, 공백 struct hostent* gethostbyname (char * name, int nameLen) /etc/hosts 파일 탐색해서 문자열 name과 연관된 파일 엔트리 구조체 hostent 포인터 반환 inet_ntoa (struct in_addr address) in_addr 구조체를 A.B.C.D 형식의 주소를 나타내는 문자열 반환 unsigned long inet_addr(char * string) 32비트 IP 주소를 반환 void bzero(char * buffer, int length) 크기가 length인 배열 buffer를 0 (Ascii Null)로 채운다. 호스트 형식을 네트워크 형식으로 Unsigned long htonl(unsigned long hostLong) Unsigned short htons(unsigned long hostShort) 네트워크 형식을 호스트 형식으로 Unsigned long ntohl(unsigned long networkLong) Unsigned short ntohs(unsigned long hostShort) Unix
13
소켓 구조. /* Definitions for UNIX IPC domain … /usr/include/sys/un.h */
struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ char sun_path[108]; /* path name (gag) */ }; /* Socket address, internet style … /usr/include/netinet/in.h */ struct sockaddr_in { sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; Unix
14
소켓 구조.. Unix /* Internet address … /usr/include/netinet/in.h
* This definition contains obsolete fields for compatibility * with SunOS 3.x and 4.2bsd. The presence of subnets renders * divisions into fixed fields misleading at best. New code * should use only the s_addr field. */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) #define _S_un_b S_un_b #define _S_un_w S_un_w #define _S_addr S_addr #define _S_un S_un #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */ struct in_addr { union { struct { uchar_t s_b1, s_b2, s_b3, s_b4; } _S_un_b; struct { ushort_t s_w1, s_w2; } _S_un_w; uint32_t _S_addr; #else in_addr_t _S_addr; } _S_un; #define s_addr _S_un._S_addr /* should be used for all code */ #define s_host _S_un._S_un_b.s_b /* OBSOLETE: host on imp */ #define s_net _S_un._S_un_b.s_b /* OBSOLETE: network */ #define s_imp _S_un._S_un_w.s_w /* OBSOLETE: imp */ #define s_impno _S_un._S_un_b.s_b /* OBSOLETE: imp # */ #define s_lh _S_un._S_un_b.s_b /* OBSOLETE: logical host */ }; Unix
15
포트 번호(Port Number) 16-비트 포트 번호
하나 이상의 프로세스가 한꺼번에 TCP나 UDP를 사용할 수 있기 위해 각 사용자 프로세스와 관련된 데이터 구분 필요 32-비트 Internet 주소로는 호스트만 접촉 가능, 특정 프로세스 가리키는 방법 필요 1~255 : 미리 할당된 포트 번호 /usr/include/netinet/in.h 에서 표준 포트(well-known ports) 확인 (예) FTP 제공 TCP/IP 포트 번호 : 21 4.3BSD : 1~1023 수퍼유저 프로세스 위해 예약 1023 < TCP의 포트 번호 < 5000 단명적 창구 번호(ephemeral(short lived) port number) : client에게 부여된 유일한 창구번호 인터넷 한벌(TCP/IP 또는 UDP/IP)에서 연결을 정의하는 5쌍 규약(TCP 또는 UDP) 지역 호스트의 Internet 주소(32-비트) 지역 포트 번호(16-비트) 상대 호스트의 Internet 주소(32-비트) 상대 포트 번호(16-비트) (예) {tcp, , 1500, , 21} Unix
16
파일기술자와 소켓기술자(소켓번호) 기술자 테이블 파일 또는 정보 구조체 5 (소켓) : pointer
기술자 테이블 파일 또는 정보 구조체 파일 기술자 또는 (파일) 소켓기술자 (파일) (소켓) : pointer family:PF_INET service :SOCK_STREAM local IP: local port: remote IP: remote port: Unix
17
IP주소변환의 세가지 방법 및 변환 함수 gethostbyname( ) inet_addr( )
cc.kangwon.ac.kr: : 도메인 네임 : IP 주소(binary) :dotted decimal gethostbyname( ) inet_addr( ) gethostbyaddr( ) inet_ntoa( ) Unix
18
응용프로그램과 소켓,TCP/IP의 관계 TCP/IP 192.203.144.11 연결형 서비스 비연결형 서비스 응용 프로그램
연결형 서비스 비연결형 서비스 응용 프로그램 (소켓번호) 소켓 (포트번호) 트랜스포트 계층 인터넷 계층 (IP주소) 네트웍 fd :File Descriptor IP:Internet Protocol sd:Socket Descriptor TCP:Transmission Control Protocol UDP:User Datagram Protocol 응용1 응용2 응용3 응용4 fd=3 sd=4 sd=3 sd=3 sd=3 TCP/IP UDP TCP I P Unix
19
inetserver.c : 인터네트 서버. /* compile : gcc -o client client.c -lsocket -lnsl */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define PORTNUM 3000 main(int argc, char *argv[]) { int serverFd, clientFd, clilen, childpid; struct sockaddr_in cli_addr, serv_addr; if((serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("server: can't open stream socket"); return -1; } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 어떤 호스트의 클라이언트도 다 받아들임 */ serv_addr.sin_port = htons(PORTNUM); /* 서버 포트 번호 */ if(bind(serverFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) printf("server: can't bind local address"); printf("Server is binded\n"); listen(serverFd, 5); Unix
20
inetserver.c : 인터네트 서버(cont.)
for( ; ; ){ /* Wait for a connection from a client process. * This is an example of a concurrent server. */ clilen = sizeof(cli_addr); clientFd = accept(serverFd, (struct sockaddr *) &cli_addr, &clilen); printf("Server called\n"); if((childpid = fork()) < 0){ printf("server: fork error"); exit(0); } else if(childpid == 0){ /* child process */ printf("serverFd = %d, clientFd = %d\n", serverFd, clientFd); /* process the request */ write(clientFd,"Hello!",7); close(clientFd); /* close original socket */ return -1; close(clientFd); /* parent process */ Unix
21
inetclient.c : 인터네트 클라이언트
/* compile : gcc -o client client.c -lsocket -lnsl */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define PORTNUM 3000 main(int argc, char *argv[]) { int clientFd; char str[10]; char* hostaddress; struct sockaddr_in serv_addr; struct hostent* hostStruct; struct in_addr* hostNode; if(argv[1] == NULL){ printf("Usage: inetclient hostname(or server IP)\n"); printf(" (Ex) inetclient isis.inchon.ac.kr(or )\n"); exit(0); } Unix
22
inetclient.c : 인터네트 클라이언트(cont.)
hostStruct = gethostbyname(argv[1]); if(hostStruct == NULL) return(0); hostNode = (struct in_addr*) hostStruct->h_addr; hostaddress = inet_ntoa(*hostNode); /* Fill in the structure "serv_addr" with the address of the * server that we want to connect with. */ bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(hostaddress); serv_addr.sin_port = htons(PORTNUM); /*Open a TCP socket (an Internet stream soskcet). */ if((clientFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("client: can't open stream socket"); /* Connect to the server */ if(connect(clientFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) printf("client: can't connect to server"); printf("clientFd = %d\n", clientFd); read(clientFd, str, 10); printf("%s\n", str); close(clientFd); exit(0); Unix
23
AF_UNIX 도메인 가위, 바위, 보 게임 서로 병렬로 수행되며 “가위 , 바위, 보” 게임을 대화형으로 수행하는 프로그램을 작성하라. 이 게임에서는 , 두 사람이 각각 상대방이 모르게 가위, 바위, 보를 선택한다. 그 후에, 각자의 선택을 공개하고 심판은 다음과 같이 승자를 정한다. 보가 바위를 이긴다. 바위가 가위를 이긴다. 가위가 보를 이긴다. 서로 같으면 비긴다. 승자가 점수 1을 얻는데, 비기는 경우에는 점수가 없다. 앞의 게임을 시뮬레이트 하는 게임 프로그램을 사용자가 게임의 반복 횟수를 선택하고 게임 진행 과정을 살펴 보고, 또한 최종 결과를 알 수 있도록 한다. 다음은 게임의 예이다. $ play 번 반복하여 게임 실행 Paper, Scissors, Rock : 3 iterations Player 1 : ready Player 2 : ready Go players [1] Player 1 : Scissors Player 2 : Rock Player 2 wins Go players [2] Player 1 : Paper Player 2 : Rock Player 1 wins Go players [3] Player 2 : Paper Player draw. Final score : Player 1 : 1 Player 2 : 1 Players Draw Unix
24
가위, 바위, 보 게임.. 다음과 같이 동작하는 3개의 프로그램을 작성하라.
첫번째 프로그램은 하나의 심판 프로세스와 2개의 경기자 프로세스들을 fork/exec하는 메인 프로그램이다. 그리고는 3개의 프로세스들이 종료되기를 기다린다. 메인 프로그램은 반복 수행 횟수를 지정하는 명령 라인의 매개 변수가 적합한가를 조사한 후, 그를 exec()에 대한 매개 변수로서 심판 프로세스에게 전달한다. 두번째 프로그램은 서버의 역할을 하는 심판 프로그램이다. 이 프로그램은 소켓을 준비하고, 두 경기자가 준비되었음을 의미하는 문자열 “READY”를 보내는 것을 기다린다. 그 후에, 각 경기자에게 문자열 “GO”를 전송해 선택하라고 전한다. 두 경기자의 응답을 읽고 그들의 점수를 계산하고 갱신한다. 이 프로세스는 모든 차례가 취해질 때까지 반복되어야 하고, 그 후 심판은 두 경기자에게 문자열 “STOP”을 전송해 그들을 종료되도록 해야 한다. 세번째 프로그램은 클라이언트의 역할을 하는 경기자 프로그램이다. 이 프로그램은 메인 프로그램에 의해 두 번 수행되는데, 심판의 소켓에 연결함으로써 시작해야 한다. 그후에 “READY” 메시지를 전송한다. 심판으로부터 “GO”메시지를 받으면, 가위, 바위, 보 중 하나를 선택하고 그를 다시 심판에게 전송해야 한다. 문자열 “STOP”을 받으면, 자신을 사멸시켜야 한다. 이 프로그램은 몇몇 함수들을 거의 확실히 공유한다. 보다 효율적으로 하기 위해서는 , 이 공통 함수들을 개별적으로 번역하고, 그들을 사용하는 수행 파일로 그들을 링크하는 makefile을 만들어라. 문자열을 1바이트 수로 부호화하여 전송함으로써 문자열 전송을 회피하면 안 된다. 문자열로 전송하는 것이 문제에서 요구하는 바이다. Unix
25
과제 7 : 문제 중 하나 선택…12/10(금)까지 문제 1 : 인터넷 채팅 프로그램
과제 7 : 문제 중 하나 선택…12/10(금)까지 문제 1 : 인터넷 채팅 프로그램 채팅 서버가 임의의 클라이언트가 채팅에 참가하는 요청을 하면 이를 채팅 참가 라스트에 추가하며, 채팅에 참가하고 있는 클라이언트들이 보내 오는 메시지를 모든 채팅 참가자에게 다시 방송하는 기능을 수행해 주도록 채팅 서버와 채팅 클라이언트 소켓 응용 프로그램을 작성하라. 문제 2 : 가위, 바위, 보 게임의 인터넷 버전 경기자들이 서로 다른 인터네트 기계에서 게임을 할 수 있는 가위, 바위 보 게임을 작성하라. … 이 명령을 호스트 xx에서 실행 … 지역포트 5000 사용 $ refree 5000 … 이 명령을 호스트 yy에서 실행 $ player xx 5000 … 이 명령을 호스트 zz에서 실행 실습 주의 사항 포트번호 수정해서 서버 실행 : 1023 < 포트번호 < 5000 실습 끝난 후 반드시 서버 프로세스 종료 : kill -9 프로세스번호(ps 명령으로 알아냄) Unix
Similar presentations