50
네네네네 네네네네네 Unix Network Programming, 2nd Ed., W. Rich ard Stevens, Prentice Hall PTR, 1999. 네네네 네 Unix Network Programming, Stevens 네 , 네네네 , 네네네 네 , 네네네 , 1991. 네네네네네네네 네네네네네 , 네네네 , 네네네 , 네네네네네네네 , 2000.

네트워크 프로그래밍

  • Upload
    hakan

  • View
    117

  • Download
    0

Embed Size (px)

DESCRIPTION

네트워크 프로그래밍. Unix Network Programming, 2nd Ed., W. Richard Stevens, Prentice Hall PTR, 1999. 한국어 판 Unix Network Programming, Stevens 저 , 김치하 , 이재용 역 , 대영사 , 1991. 컴퓨터네트워크 프로그래밍 , 개정판 , 김화종 , 홍릉과학출판사 , 2000. 10.7 소켓. 프로세스간 상호 양방향 통신 방식 네트워크를 통한 통신 가능 - PowerPoint PPT Presentation

Citation preview

Page 1: 네트워크 프로그래밍

네트워크 프로그래밍

Unix Network Programming, 2nd Ed., W. Richard Stevens, Prentice Hall PTR, 1999.

한국어 판 Unix Network Programming, Stevens 저 , 김치하 , 이재용 역 , 대영사 , 1991.

컴퓨터네트워크 프로그래밍 , 개정판 , 김화종 , 홍릉과학출판사 , 2000.

Page 2: 네트워크 프로그래밍

10. 시스템 프로그래밍 2

10.7 소켓

프로세스간 상호 양방향 통신 방식 네트워크를 통한 통신 가능 소켓을 통한 프로세스 통신은 클라이언트 - 서버 모델 (client-server

model) 에 기초

활용 한 기계에 존재하는 파일을 다른 기계에서 프린트 한 기계에서 다른 기계로 파일을 전송

Page 3: 네트워크 프로그래밍

10. 시스템 프로그래밍 3

인터넷에서의 데이터 흐름

Transport

포장 벗겨 위로 전달

Application

Network

LinkNetwork

Link

Network

Link

Application

Transport

Network

Link

도착주소 (IP) 전달

세그먼트 분할+ 포장 +도착주소

중간주소 붙여 포장( 도착주소 or라우터주소 )

중간주소를 local network 주소로 변환

포장 벗겨 도착주소 확인 후 아니면 다시 포장 + 새중간주소 (옆의 다른 라우터 주소)

메시지 재구성

포장 벗겨 도착주소 확인 맞으면 위로 전달

포장 벗겨 위로 전달

Page 4: 네트워크 프로그래밍

10. 시스템 프로그래밍 4

연결형 시스템 호출 연결형 소켓 (connection oriented protocol :

TCP(Transmission Control Protocol)서버 (server) 클라이언트 (client)

클라이언트로부터 연결이 올 때까지 대기

프로세스에 요청

read( )

bind( )

listen( )

accept( )

socket( )

write( )

socket( )

connect( )

write( )

read( )Data 응답

Data 요청

연결설정

[ 참고 P535]

Page 5: 네트워크 프로그래밍

10. 시스템 프로그래밍 5

비연결형 소켓 시스템 호출

Server(connectionless protocol : UDP(User Datagram Protocol))

Client

blocks until data received from a client data(request) process request data(reply)

socket()

write()

bind()

socket()

bind()

read()

sendto()

recvfrom()

Page 6: 네트워크 프로그래밍

10. 시스템 프로그래밍 6

서버

서버

서버

클라이 언트

클라이 언트

이름

이름

이름

완결된 연결

서버가 명명된 소켓 을 생성

클라이언트가 명명되지 않은 소켓을 생성하고 , 연결을 요청

클라이언트가 연결됨 . 서버는 원래 명명된 소켓을 유지

10.7 소켓

소켓 연결과정

Page 7: 네트워크 프로그래밍

10. 시스템 프로그래밍 7

10.7 소켓

여러 종류의 소켓 다음의 속성에 따라 분류

• 도메인 (domain)» 서버와 클라이언트 소켓이 존재하는 장소를 지칭

• 유형 (type)» 클라이언트와 서버 사이에 존재할 수 있는 통신의 유형을 결정

• 프로토콜 (protocol)» 소켓 유형을 구현하는 저급의 수단을 명시

도메인 : 서버와 클라이언트 소켓이 존재하는 장소를 지칭 AF : “ Address Family ”

• AF_UNIX» 클라이언트와 서버는 동일한 기계에 존재해야 함

• AF_INET» 클라이언트와 서버는 인터네트 어느 곳에서든지 존재할 수 있음

• AF_NS» 클라이언트와 서버는 XEROX 네트워크 시스템에 존재할 수 있음

Page 8: 네트워크 프로그래밍

10. 시스템 프로그래밍 8

10.7 소켓 유형 : 클라이언트와 서버와의 통신의 유형 결정

• SOCK_STREAM» 일련 번호가 붙은 , 신뢰적 , 양방향 연결에 기초한 바이트의 가변

길이의 스트림• SOCK_DGRAM

» 전보와 비슷한 , 무연결 , 비신뢰적 고정 길이의 메시지• SOCK_SEQPACKET

» 일련번호가 붙은 , 신뢰적 , 양방향 연결에 기초한 바이트의 고정 길이 패킷

• SOCK_RAW» 내부 네트워크 프로토콜과 인터페이스에 대한 접근 제공

Page 9: 네트워크 프로그래밍

10. 시스템 프로그래밍 9

10.7 소켓

• 도메인과 소켓 유형간의 모든 조합이 허용되지는 않음

» “Yes” 라 표시된 부분은 채울 약어가 없으며 ,» 빈 부분은 구현되지 않은 부분이다 .

AF_UNIX AF_INET AF_NS

SOCK_STREAM

SOCK_DGRAM

SOCK_RAW

SOCK_SEQPACKET

Yes

Yes

TCP

UDP

IP

SPP

IDP

Yes

SPP

[ 참고 ]

Page 10: 네트워크 프로그래밍

10. 시스템 프로그래밍 10

10.7 소켓

소켓 프로그램 작성• 소켓 사용시 아래의 파일 포함

» /usr/include/sys/types.h

» /usr/include/sys/socket.h 포함 • 소켓 도메인에 따라 헤더파일 포함

• 소스 프로그램 : P525

도메인 추가할 헤더 파일 AF_UNIX

AF_INET

/usr/include/sys/un.h

/usr/include/netinet/in.h/usr/include/arpa/inet.h/usr/include/netdb.h

Page 11: 네트워크 프로그래밍

10. 시스템 프로그래밍 11

10.7 소켓

서버• 명명된 소켓을 생성하고 , 생성한 소켓으로의 • 연결을 수용하는 것을 책임지는 프로세스 • 다음의 순서대로 시스템호출을 사용

의 미명 칭 socket

bind

listen

accept

명명되지 않은 소켓을 생성 소켓에 이름을 부여 대기중인 연결의 최대 수를 명시 클라이언트로부터의 소켓 연결을 수용

Page 12: 네트워크 프로그래밍

10. 시스템 프로그래밍 12

10.7 소켓

소켓의 생성 : socket( ) • socket( ) 을 사용하여 소켓 생성

• 동작

» 명시된 domain, type, protocol 의 명명되지 않은 소켓을 생성

» 소켓 생성 성공시 : 새로 생성된 소켓에 연관된 파일 기술자 (serverFd) 를 반환

» 소켓 생성 실패시 : 파일 기술자 (serverFd) 에 -1 반환

serverFd = socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL);

System call: int socket ( int domain, int type, int protocol )

Page 13: 네트워크 프로그래밍

10. 시스템 프로그래밍 13

10.7 소켓

소켓에 이름 부여 : bind( )• 서버가 명명되지 않은 소켓 생성시 , bind( ) 를 사용하여 이름 부여

• 성공시 0 을 반환 , 실패시 -1 을 반환

• 동작

» address 에 저장된 소켓 주소를 가지는 파일 기술자 fd 를 명명되지 않은 소켓에 연관시킴

» addressLen 는 주소 구조체의 길이를 포함

» 입력될 주소의 유형과 값은 소켓 도메인에 의함

System call: int bind ( int fd, struct sockaddr* address, int addressLen )

Page 14: 네트워크 프로그래밍

10. 시스템 프로그래밍 14

10.7 소켓 도메인에 따른 구조체 항목

• AF_UNIX 도메인 » sockaddr_un 구조체의 항목

• AF_INET 도메인 » sockaddr_in 구조체의 항목

항목 값부여sun_family AF_UNIX

sun_path 소켓의 완전한 경로 이름으로 ,

최대 길이는 180 문자

항목 값부여sin_family AF_INET

sin_port 인터네트 소켓의 포트 번호sin_addr in_addr 유형의 구조체sin_zero 공백상태로 남겨둔다

Page 15: 네트워크 프로그래밍

10. 시스템 프로그래밍 15

10.7 소켓

소켓 큐 생성 : listen( ) • 대기 중인 소켓 연결의 최대 수를 명시 • 만일 , 클라이언트가 가득 차 있는 큐를 소켓에 연결하려고 한다면 , 그

연결은 거부됨 • 동작

예 ) listen (serverFd, 5); /* 대기 중인 연결의 최대 길이 */

System call: int listen ( int fd, int queueLength )

Page 16: 네트워크 프로그래밍

10. 시스템 프로그래밍 16

10.7 소켓

클라이언트 수용 : accept( )• 클라이언트의 연결 요구 수용• 기술자를 반환하며 , 실패시에는 -1 반환• accept( ) 가 성공 시 통신에 사용될 수 있는 새로운 파일• 동작

» address 구조체 : 클라이언트의 주소 , 보통 인터넷 연결과 관련되어서만 사용

» addressLen : address 에 의해서 지정되는 구조체의 크기를 포함하는 정수

System call: int bind ( int fd, struct sockaddr* address, int addressLen )

Page 17: 네트워크 프로그래밍

10. 시스템 프로그래밍 17

10.7 소켓

클라이언트 명명되지 않은 소켓을 생성하고 , 생성한 소켓을 명명된 서버소켓으로의

접속을 책임지는 프로세스 다음의 순서대로 시스템호출을 사용

명칭 의미

socket( )

connect( )

명명되지 않은 소켓을 생성

명명되지 않은 클라이언트 소켓을 명명된 서버 소켓에 접속

Page 18: 네트워크 프로그래밍

10. 시스템 프로그래밍 18

10.7 소켓

연결하기 : connect( ) • 서버의 소켓에 연결

• connect( ) 성공시 0 반환하고 , 서버 소켓이 존재 하지 않거나 , 대기 큐가 가득차 있으면 -1 반환

• 동작

» address 구조체내에 주소가 저장되어 있는 서버소켓에 연결을 시도

» 연결 성공시 , fd 는 서버의 소켓과 통신하기 위해 사용

» addressLen 은 주소 구조체의 크기와 동일

System call:int connect( int fd, struct sockaddr* address, int addressLen )

Page 19: 네트워크 프로그래밍

10. 시스템 프로그래밍 19

10.7 소켓

인터네트 소켓 : IP 주소와 PORT 주소에 의해 명시 32bit IP 주소와 16bit port 번호 필요

• 인터네트 주소 종류 » “s” 는 지역 호스트를 의미» 숫자로 시작 : A.B.C.D 형식의 IP 주소로 가정

소프트웨어에 의해서 32bit 의 IP 주소로 변환

» 문자열 입력 : 기호적 호스트 이름으로 가정 소프트웨어에 의해 32bit IP 주소로 변환

Inettime 소스 프로그램 : p536 ~ p538 (debugging)

Page 20: 네트워크 프로그래밍

10. 시스템 프로그래밍 20

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; /* 클라이언트 주소에 대한 포인터 */

/* 좀비를 방지하기 위해 자식 - 죽음 시그널은 무시 */ signal(SIGCHLD, SIG_IGN);

serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress; serverLen = sizeof(serverUNIXAddress); clientSockAddrPtr = (struct sockaddr*) &clientUNIXAddress; clientLen = sizeof(clientUNIXAddress);

Page 21: 네트워크 프로그래밍

10. 시스템 프로그래밍 21

Chef.c (cont)/* 양방향 , 디폴트 프로토콜의 유닉스 소켓 생성 */ 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); /* 두번째 줄 쓰기 */ }

Page 22: 네트워크 프로그래밍

10. 시스템 프로그래밍 22

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"); /* 서버 이름 */

do { /* 서버와 연결되기까지 루프 */ result = connect (clientFd, serverSockAddrPtr, serverLen); if(result == -1) sleep(1); /* 대기후 다시 시도 */ } while(result == -1);

Page 23: 네트워크 프로그래밍

10. 시스템 프로그래밍 23

Cook.c (cont)

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);}

Page 24: 네트워크 프로그래밍

10. 시스템 프로그래밍 24

inettime.c: 인터네트 시간청취

#include <stdio.h>#include <signal.h>#include <ctype.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h> /* For AFINET sockets */#include <arpa/inet.h>#include <netdb.h>#define DAYTIME_PORT 13 /* Standard port o */#define DEFAULT_PROTOCOL 0unsigned long promptForINETAddress ();unsigned long nameToAddr ();main (){ int clientFd; /* Client socket file descriptor */ int serverLen; /* Length of server address structure */ int result; /* From connect () call */ struct sockaddr_in serverINETAddress; /* Server address */ struct sockaddr* serverSockAddrPtr; /* Pointer to address */ unsigned long inetAddress; /* 32-bit IP address */ /* Set the two server variables */ serverSockAddrPtr = (struct sockaddr*) &serverINETAddress;

Page 25: 네트워크 프로그래밍

10. 시스템 프로그래밍 25

inettime.c: 인터네트 시간청취 (cont.)

serverLen = sizeof (serverINETAddress); /* Length of address */ while (1) /* Loop until break */ { inetAddress = promptForINETAddress (); /* Get 32-bit IP */ if (inetAddress == 0) break; /* Done */ /* Start by zeroing out the entire address structure */ bzero ((char*)&serverINETAddress,sizeof(serverINETAddress)); serverINETAddress.sin_family = AF_INET; /* Use Internet */ serverINETAddress.sin_addr.s_addr = inetAddress; /* IP */ serverINETAddress.sin_port = htons (DAYTIME_PORT); /* Now create the client socket */ clientFd = socket (AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL); do /* Loop until a connection is made with the server */ { result = connect (clientFd,serverSockAddrPtr,serverLen); if (result == -1) sleep (1); /* Try again in 1 second */ } while (result == -1); readTime (clientFd); /* Read the time from the server */ close (clientFd); /* Close the socket */ } exit (/* EXIT_SUCCESS */ 0);}

Page 26: 네트워크 프로그래밍

10. 시스템 프로그래밍 26

inettime.c: 인터네트 시간청취 (cont.)

unsigned long promptForINETAddress (){ char hostName [100]; /* Name from user: numeric or symbolic */ unsigned long inetAddress; /* 32-bit IP format */ /* Loop until quit or a legal name is entered */ /* If quit, return 0 else return host's IP address */ do { printf ("Host name (q = quit, s = self): "); scanf ("%s", hostName); /* Get name from keyboard */ if (strcmp (hostName, "q") == 0) return (0); /* Quit */ inetAddress = nameToAddr (hostName); /* Convert to IP */ if (inetAddress == 0) printf ("Host name not found\n"); } while (inetAddress == 0);}unsigned long nameToAddr (name)char* name;{ char hostName [100]; struct hostent* hostStruct; struct in_addr* hostNode; /* Convert name into a 32-bit IP address */ /* If name begins with a digit, assume it's a valid numeric */ /* Internet address of the form A.B.C.D and convert directly */ if (isdigit (name[0])) return (inet_addr (name));

Page 27: 네트워크 프로그래밍

10. 시스템 프로그래밍 27

inettime.c: 인터네트 시간청취 (cont.)

if (strcmp (name, "s") == 0) /* Get host name from database */ { gethostname (hostName,100); printf ("Self host name is %s\n", hostName); } else /* Assume name is a valid symbolic host name */ strcpy (hostName, name); /* Now obtain address information from database */ hostStruct = gethostbyname (hostName); if (hostStruct == NULL) return (0); /* Not Found */ /* Extract the IP Address from the hostent structure */ hostNode = (struct in_addr*) hostStruct->h_addr; /* Display a readable version for fun */ printf ("Internet Address = %s\n", inet_ntoa (*hostNode)); return (hostNode->s_addr); /* Return IP address */ }readTime (fd) int fd; { char str [200]; /* Line buffer */ printf ("The time on the target port is "); while (readLine (fd, str)) /* Read lines until end-of-input */ printf ("%s\n", str); /* Echo line from server to user */ }

Page 28: 네트워크 프로그래밍

10. 시스템 프로그래밍 28

inettime.c: 인터네트 시간청취 (cont.)

readLine (fd, str) int fd; char* str; /* Read a single NEWLINE-terminated line */ { int n; do /* Read characters until NULL or end-of-input */ { n = read (fd, str, 1); /* Read one character */ } while (n > 0 && *str++ != '\n'); return (n > 0); /* Return false if end-of-input */ }

Page 29: 네트워크 프로그래밍

10. 시스템 프로그래밍 29

10.7 소켓 인터네트 클라이언트

소켓 도메인 : AF_INET 소켓 주소 구조체 (sockaddr_in) 의 4항목

• sin_family : 소켓의 도메인으로 , AF_INET 로 설정

• sin_port : 포트 번호 지정

• sin_addr : 클라이언트 / 서버의 32bit IP 주소

• sin_zero : 삽입구로 , 공백상태로 남겨둠

인터네트 서버 소켓 주소 구조체의 항목은 클라이언트 항목과 같게

• sin_port 항목은 INADDR_ANY로 설정 , 이것은 “어떠한 입력 클라이언트 요구들도 받아들인다”는 것을 의미

struct sockaddr_in serverINETAddress; /* 서버 인터네트 주소 */

serverINETAddress.sin_family = AF_INET; /* 인터네트 도메인 */

serverINETAddress.sin_addr.s_addr = htonl(INADDR_ANY);

/* 모두 받아들임 */

serverINETAddress.sin_port = htons(port); /* 서버 포트 번호 */

Page 30: 네트워크 프로그래밍

10. 시스템 프로그래밍 30

10.7 소켓

Library call: unsigned long inet_addr(char* string)

A.B.C.D 형식의 string 에 해당하는 32bit 주소로 변환

system call: int gethostname(char* name, int nameLen)

길이가 nameLen 인 name 이 가리키는 문자배열은 지역 호스트 이름과 동일한 NULL 로 끝나는 문자열로 설정

Library call: struct hostent* gethostbyname(char* name)

“/etc/hosts” 파일 탐색하여 , 문자열 name 과 연관된 파일 엔트리로 묘사하는 구조체 hostent 를 가리키는 포인터로 반환만일 , name 이 “ /etc/hosts” 파일에서 발견되지 않으면 NULL 반환

Page 31: 네트워크 프로그래밍

10. 시스템 프로그래밍 31

10.7 소켓

Library call: char* inet_ntoa(struct in_addr address)

인수로 in_addr 형의 구조체를 취하고 , A.B.C.D 형식으로 주소를 묘사하는 문자열에 대한 포인터를 반환

Library call: void bzero(char* buffer, int length)

크기가 length 인 buffer 를 0(ASCII NULL) 로 채움

Library call: unsigned long htonl(unsigned long hostLong)

호스트 형식인 unsigned long 유형의 hostLong 과 동등한 네트워크 형식을 반환

Library call: unsigned short ntohs(unsigned long hostLong)

네트워크 형식인 unsigned short 유형의 networkshort 와 동등한 호스트 형식을 반환

Page 32: 네트워크 프로그래밍

10. 시스템 프로그래밍 32

10.7 소켓

인터네트 서버 소켓 주소 구조체의 항목은 클라이언트 항목과 같게

• sin_port 항목은 INADDR_ANY로 설정 , 이것은 “어떠한 입력 클라이언트 요구들도 받아들인다”는 것을 의미

struct sockaddr_in serverINETAddress; /* 서버 인터네트 주소 */

serverINETAddress.sin_family = AF_INET; /* 인터네트 도메인 */

serverINETAddress.sin_addr.s_addr = htonl(INADDR_ANY);

/* 모두 받아들임 */

serverINETAddress.sin_port = htons(port); /* 서버 포트 번호 */

Page 33: 네트워크 프로그래밍

10. 시스템 프로그래밍 33

IP 주소변환의 세가지 방법 및 변환 함수

Media.inchon.ac.kr: :192.203.144.1

도메인 네임 : IP 주소 (binary) :dotted decimal

gethostbyname( ) inet_addr( ) gethostbyaddr( ) inet_ntoa( )

11000011 11001011 10010000 00001011

Page 34: 네트워크 프로그래밍

10. 시스템 프로그래밍 34

파일기술자와 소켓기술자 ( 소켓번호 )

pointer

pointer

pointer

family:PF_INET

service :SOCK_STREAM

local IP:

local port:

remote IP:

remote port:

:

:

기술자 테이블 파일 또는 정보 구조체

( 파일 ) 파일 기술자 또는 3 소켓기술자 4 ( 파일 ) 5 ( 소켓 )

Page 35: 네트워크 프로그래밍

10. 시스템 프로그래밍 35

응용프로그램과 소켓 ,TCP/IP 의 관계 연결형 서비스 비연결형 서비스 응용 프로그램 ( 소켓번호 )

소켓

( 포트번호 ) 트랜스포트 계층

인터넷 계층 (IP 주소 )

네트워크fd :File Descriptor IP:Internet Protocol sd:Socket DescriptorTCP:Transmission Control Protocol UDP:User Datagram Protocol

응응 응응

응응

응응

fd=3 sd=4 sd=3 sd=3 sd=3

TCP/IP

TCP UDP

I P

Page 36: 네트워크 프로그래밍

10. 시스템 프로그래밍 36

소켓 구조

/* 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;

Page 37: 네트워크 프로그래밍

10. 시스템 프로그래밍 37

소켓 구조/* 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;#if !defined(_XPG4_2) || defined(__EXTENSIONS__) uint32_t _S_addr;#else in_addr_t _S_addr;#endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */ } _S_un;#define s_addr _S_un._S_addr /* should be used for all code */#define s_host _S_un._S_un_b.s_b2 /* OBSOLETE: host on imp */#define s_net _S_un._S_un_b.s_b1 /* OBSOLETE: network */#define s_imp _S_un._S_un_w.s_w2 /* OBSOLETE: imp */#define s_impno _S_un._S_un_b.s_b4 /* OBSOLETE: imp # */#define s_lh _S_un._S_un_b.s_b3 /* OBSOLETE: logical host */};

Page 38: 네트워크 프로그래밍

10. 시스템 프로그래밍 38

포트 번호 (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

인터넷 한벌 (TCP/IP 또는 UDP/IP) 에서 연결을 정의하는 5쌍• 규약 (TCP 또는 UDP)• 지역 호스트의 Internet 주소 (32- 비트 )• 지역 포트 번호 (16- 비트 )• 상대 호스트의 Internet 주소 (32- 비트 )• 상대 포트 번호 (16- 비트 )( 예 ) {tcp, 128.10.0.3, 1500, 128.10.0.7, 21}

Page 39: 네트워크 프로그래밍

10. 시스템 프로그래밍 39

inetserver.c : 인터네트 서버/* compile : gcc -o client client.c -lsocket -lnsl *//* execute : server */#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#define PORTNUM 3000main(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);

Page 40: 네트워크 프로그래밍

10. 시스템 프로그래밍 40

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 */ }}

Page 41: 네트워크 프로그래밍

10. 시스템 프로그래밍 41

inetclient.c : 인터네트 클라이언트/* compile : gcc -o client client.c -lsocket -lnsl *//* execute : inetclient hostname(or server IP) */#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#define PORTNUM 3000main(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 210.126.35.99)\n"); exit(0); }

Page 42: 네트워크 프로그래밍

10. 시스템 프로그래밍 42

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);

Page 43: 네트워크 프로그래밍

10. 시스템 프로그래밍 43

10.8 인터네트 셸

설계 파이프와 후면 처리 기능 제공

표준 유닉스 셸과 유사하면서 , 인터네트 - 명시적 기능 추가

셸의 기능을 적합한 크기로 구성하기 위해 제한 모든 토큰 (token) 은 공란 (tab 또는 space) 에 의해서 분리

파일 이름 대치는 지원되지 않음

Page 44: 네트워크 프로그래밍

10. 시스템 프로그래밍 44

10.8 인터네트 셸

명령 구문 : 표준 유닉스 셸의 명령어 구문과 유사

<internetshellcommand> = <sequence> [ & ]<sequence> = <pipeline> { ; <pipeline> }* <pipeline> = <simple> { | <simple> } <simple> = { <token> }* { <redirection> }* <redirection> = <fileRedirection> | <socketRedirection> <fileRedirection> = \> <file> | >> <file> | \< <file> <socketRedirection> = <clientRedirection> | <serverRedirection> <clientRedirection> = @\>c <socket> | @\<c <socket> <serverRedirection> = @\>s <socket> | @\<s <socket> <token> = a string of chracters <file> = a valid UNIX pathname <socket> = either a UNIX pathname ( UNIX domain socket ) or an Internet socket name of the form hostname.port#

Page 45: 네트워크 프로그래밍

10. 시스템 프로그래밍 45

10.8 인터네트 셸

인터네트 셸 시작하기• 인터네트 셸 실행 파일 이름 : ish

• 인터네트 셸 프롬프트 : 의문부호 (?)

• ish 시작시 자신을 호출한 셸에서 $PATH 환경변수를 상속받음» $PATH 값은 내장명령어 setenv 를 사용해 변경 가능

» 인터네트 셸 종료시 : control-D

내장 명령어

소스 프로그램 : P553

내장 명령어 기능echo { <token> }* 터미널에 token 을 에코 (echo)

cd path 셸의 작업 디렉토리를 path 로 변경getenv name 환경 변수 name 의 값을 표시setenv name value 환경 변수 name 의 값을 value 로 설정

Page 46: 네트워크 프로그래밍

10. 시스템 프로그래밍 46

소켓 응용 프로그램

인터넷 토크 프로그램 netprog 의 talk_server.c talk_client.c 소스코드 참조 실행

% talk_server 포트번호% talk_client 서버호스트 IP 주소 포트번호

인터넷 채팅 프로그램 하나의 프로세스가 채팅 참가 신청 처리와 클라이언트들의 통신 처리를

다 할 수 있도록 accept() 또는 read() 에서 계속 기다리는 동기 (synchronous, blocking) 모드 대신 select() 시스템 호출을 이용하여 소켓을 비동기 (asynchronous, non-blocking) 모드로 이용

netprog 의 chat_server.c chat_client.c 소스 코드 참조 실행

% chat_server 포트번호% chat_client 서버호스트 IP 주소 포트번호

Page 47: 네트워크 프로그래밍

10. 시스템 프로그래밍 47

select()

select() 소켓에서 발생하는 I/O 변화를 기다리다가 지정된 /O 변화가 발생하면 리턴 됨 초기 소켓 s 와 참가한 클라이언트들의 소켓의 I/O 변화 감지

select() 시스템 호출 형식int select (int maxfdp1, /* chleo 파일 (및 소켓 ) 번호 크기 +1 */fd_set *readfds, /* 읽기 상태 변화를 감지할 소켓 지정 */ fd_set *writefds, /* 쓰기 상태 변화를 감지할 소켓 지정 */fd_set *exceptfds, /* 예외 상태 변화를 감지할 소켓 지정 */ struct timeval *tvptr); /*select() 시스템 호출이 기다리는 시간 */

FD_ZERO(fd_set *fdset) 매크로로 모든 비트 지움 FD_SET(int fd, fd_set *fdset) 매크로로 소켓 fd 의 fdset 변화를 감지하기

위해 fdset 중 fd 에 해당하는 비트를 1 로 지정 FD_ISSET(int fd, fd_set *fdset) 매크로는 fdset 의 해당 fd 비트가 1 로

지정되어 있으면 양수값 리턴하므로 fd 에게 fdset 변화가 발생했는지 판단

Page 48: 네트워크 프로그래밍

10. 시스템 프로그래밍 48

X 윈도우 프로그램과 시스템 관리

X 윈도우 프로그래밍 /usr/X/demo 실행해 보기

• puzzle• spider• xeyes• xsol• 등

X manager : http://www.netsarang.co.kr 에서 30 일 버전 다운로드

Http://marvel.inchon.ac.kr/~mysung Lecture Notes X Window Program 참조

Anonymous ftp multi cd pub/xprog 참조 시스템 관리

Http://marvel.inchon.ac.kr/~mysung Lecture Notes System Administration 참조

Page 49: 네트워크 프로그래밍

10. 시스템 프로그래밍 49

과제 … 12/23( 월 ) 까지 문제 1 : 가위 , 바위 , 보 게임의 인터넷 버전

두 명의 경기자들이 서로 다른 인터네트 기계에서 게임을 할 수 있는 가위 , 바위 보 게임을 작성하라 .

… 이 명령을 호스트 xx 에서 실행 … 지역포트 5000 사용$ refree 5000 … 이 명령을 호스트 yy 에서 실행$ player xx 5000… 이 명령을 호스트 zz에서 실행$ player xx 5000

문제 2 : 인터넷 채팅 프로그램 채팅 서버가 임의의 클라이언트가 채팅에 참가하는 요청을 하면 이를 채팅 참가자 리스트에 추가하며 채팅에 참가하고 있는 클라이언트들이 보내 오는 메시지를 모든 채팅 참가자에게 다시 방송하는 기능을 수행해 주는 chat_server 와 chat_client 인터넷 채팅 프로그램을 실행하고 분석해 보고 , 이 채팅 프로그램에 채팅 참가자 목록을 보여주는 ?who 명령을 추가 하라 .

실습 주의 사항 포트번호 수정해서 서버 실행 : 1023 < 포트번호 < 5000 실습 끝난 후 반드시 서버 프로세스 종료 : kill -9 프로세스번호 (ps 명령으로 알아냄 )

Page 50: 네트워크 프로그래밍

오 ! 유닉스

유닉스는 재미있다 . 유닉스는 사용하기는 쉽지만 배우기는 어렵다 . 유닉스의 모든 것을 배우는 것은 불가능하다 . 필요한 것과

재미있을 것 같다고 생각되는 부분에 관심을 쏟는 것이 좋다 . 유닉스는 세련되고 영리한 사람들을 위한 도구의 집합이다 .

수고 하셨습니다 !