얇지만 얇지 않은 tcp/ip 소켓 프로그래밍 c 2 판

71
얇얇얇 얇얇 얇얇 TCP/IP 얇얇 얇얇얇얇얇 C 2 얇 (TCP/IP Sockets in C 2/e, Morgan Kaufmann) 마마마 마마마 (Michael J. Donahoo) 마마마 마마마 (Kenneth L. Calvert)

Upload: ian-young

Post on 30-Dec-2015

229 views

Category:

Documents


6 download

DESCRIPTION

얇지만 얇지 않은 TCP/IP 소켓 프로그래밍 C 2 판. (TCP/IP Sockets in C 2/e, Morgan Kaufmann). 마이클 도나후 (Michael J. Donahoo) 케네스 칼버트 (Kenneth L. Calvert). Chapter 06 Beyond Basic Socket Programming. 제 6 장 중급 소켓 프로그래밍. 6.1 소켓 옵션 6.2 시그널 6.3 넌블로킹 입 / 출력 6.4 멀티태스킹 6.5 멀티플렉싱 6.6 다수의 수신자 처리. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

얇지만 얇지 않은

TCP/IP 소켓 프로그래밍 C 2판

(TCP/IP Sockets in C 2/e, Morgan Kaufmann)

마이클 도나후 (Michael J. Donahoo)케네스 칼버트 (Kenneth L. Calvert)

Page 2: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

2

Chapter 06 Beyond Basic Socket Chapter 06 Beyond Basic Socket ProgrammingProgramming

제 6 장 중급 소켓 프로그래밍

• 6.1 소켓 옵션• 6.2 시그널• 6.3 넌블로킹 입 /출력• 6.4 멀티태스킹• 6.5 멀티플렉싱• 6.6 다수의 수신자 처리

Page 3: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

3

소켓 옵션소켓 옵션

• 소켓 옵션 (socket options)– 소켓의 기본 동작을 변경

• 소켓 코드와 프로토콜 구현 코드에 대한 세부적인 제어 가능

• 소켓 옵션 관련 함수

– s : 소켓번호– level : 프로토콜 레벨

• SOL_SOCKET: 소켓의 일반적인 옵션 변경• IPPROTO_IP: IP 프로토콜에 관한 옵션 변경• IPPROTO_TCP: TCP 에 관한 옵션 변경

– opt : 사용하고자 하는 옵션– optval : 옵션 지정에 필요한 값의 포인터– optlen : optval 의 크기

#include <sys/types.h>#include <sys/socket.h>

int setsockopt(int s, int level, int opt, const char *optval, int optlen);int getsockopt(int s, int level, int opt, const char *optval, int *len);

Page 4: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

4

Socket Option LayerSocket Option Layer

• level– SOL_SOCKET

• 프로토콜과 무관한 소켓 그 자체

– IPPROTO_TCP• TCP 에 관련된 옵션

– IPPROTO_IP• IP 에 관련된 옵션

Page 5: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

5

SOL_SOCKETSOL_SOCKET

• Option name– SO_BROADCAST: 방송형 메시지 전송 허용– SO_DEBUG: DEBUG 모드를 선택– SO_REUSEADDR: 주소 재사용 선택– SO_LINGER

• 소켓을 닫을 때 미전송된 데이터가 있어도 지정된 시간만큼 기다렸다가 소켓을 닫음

– SO_KEEPALIVE: TCP 의 keep-alive 동작 선택– SO_OOBINLINE: OOB 데이터를 일반 데이터처럼 읽음– SO_RCVBUF: 수신버퍼의 크기 변경– SO_SNDBUF: 송신버퍼의 크기 변경

Page 6: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

6

TCP Timer TCP Timer

• TCP Retransmission Timer

• TCP Persist Timer

• TCP Keepalive Timer

• TCP Time-Waited Timer

Page 7: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

7

소켓 옵션 예제소켓 옵션 예제 ) Socket ) Socket 내부 내부 buffer buffer 변경변경• TCP, UDP 는 송신버퍼와 수신버퍼를 가짐

– TCP 의 경우 write() 호출 시 데이터를 송신 버퍼로 복사– 데이터가 송신버퍼에 모두 복사되면 시스템이 데이터를 전송– 전송 데이터는 유지하고 있다가 ACK 를 수신 후 삭제– 송신버퍼가 가득 차면 write() 는 블록됨– 송신 /수신버퍼의 크기를 사용자가 지정할 수 있음

• SO_SNDBUF– 송신 버퍼의 크기 확인 및 지정

• SO_RCVBUF– 수신 버퍼의 크기 확인 및 지정

• 송신 /수신 버퍼의 크기 지정 방법– 연결설정 (3-way handshake) 후에는 버퍼 크기 변경이 불가

• 서버의 경우 listen() 호출 이전에 설정• 클라이언트의 경우 connect() 호출 이전에 설정

Page 8: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

8

소켓 옵션 예제소켓 옵션 예제 ) Socket ) Socket 내부 내부 buffer buffer 변경변경int optval;int optlen = sizeof(optval);if(getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, (char *)&optval, &optlen) == SOCKET_ERROR)

err_quit("getsockopt()");

printf(" 수신 버퍼 크기 = %d 바이트 \n", optval);

optval = 2;if(setsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, (char *)&optval, sizeof(optval)) == SOCKET_ERROR)

err_quit("setsockopt()");

Page 9: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

9

소켓 옵션 예제소켓 옵션 예제 ) SO_REUSEADDR ) SO_REUSEADDR 옵션옵션

• 용도– 사용 중인 IP 주소와 포트 번호를 재사용

• 사용중인 IP 주소와 포트 번호로 bind() 함수를 ( 성공적으로 ) 호출할 수 있음

• 목적– 서버 종료 후 재실행시 bind() 함수에서 오류가 발생하는 것을

방지• fork() 의 부모 프로세스 문제등

Page 10: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

10

소켓 옵션 예제소켓 옵션 예제 ) SO_REUSEADDR) SO_REUSEADDR

serv_sock=socket(PF_INET, SOCK_STREAM, 0);optlen = sizeof(option);option = TRUE; // #define TRUE 1setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR,

&option, sizeof(option));

Page 11: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

11

Socket Option LayerSocket Option Layer

• level– SOL_SOCKET

• 프로토콜과 무관한 소켓 그 자체

– IPPROTO_IP• IP 에 관련된 옵션

– IPPROTO_TCP• TCP 에 관련된 옵션

Page 12: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

12

IPPROTO_IPIPPROTO_IP

• IP_TTL– Time To Live 변경

• IP_MULTICAST_TTL– 멀티캐스트 데이터그램의 TTL 변경

• IP_ADD_MEMBERSHIP– 멀티캐스트 그룹에 가입

• IP_DROP_MEMBERSHIP– 멀티캐스트 그룹에서 탈퇴

• IP_MULTICAST_LOOP– 멀티캐스트 데이터그램의 loopback 허용 여부

• IP_MULTICAST_IF– 멀티캐스트 데이터그램 전송용 인터페이스 지정

Page 13: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

13

멀티캐스트 (Multicast)

1. 전송 방식 .- UDP 를 기반으로 하는 전송 방식 .- 멀티캐스트 그룹을 기반으로 멀티캐스트 패킷을 주고 받음 .- 하나의 멀티캐스트 패킷은 라우터를 통해서 다수의 호스트에 전송 .

Page 14: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

14

멀티캐스트 (Multicast)

2. 라우팅 (Routing) 과 TTL(Time To Live)- 라우터에 의해서 패킷이 경로를 찾는 과정을 라우팅이라 한다 .- 멀티캐스트 패킷 내에는 TTL 정보가 포함된다 . TTL 은 거쳐 갈 수 있는 라우터의 수를 의미한다 .

Page 15: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

15

멀티캐스트 (Multicast)

3. 멀티캐스트 Sender 와 Receiver.- Sender : 임의의 멀티캐스트 그룹에 데이터를 전송하는 호스트- Receiver : 임의의 멀티캐스트 그룹으로부터 데이터를 수신하는 호스트 ,

4. 멀티캐스트 Sender 와 Receiver 의 구현

Sender Receiver

• UDP 소켓 생성 .

• TTL 설정 ( 소켓 옵션 설정 ). • 멀티캐스트 그룹으로 데이터 전송 .

• UDP 소켓 생성 .

• 멀티캐스트 그룹 지정 (ip_mreq 구조체 ).

• 멀티캐스트 그룹 가입 ( 소켓 옵션 설정 ).

Page 16: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

16

브로드캐스트 (Broadcast)

1. 전송 방식 .- UDP 를 기반으로 하는 전송 방식 ( 멀티캐스트와 같다 ).

- 일반적인 UDP 패킷과의 차이점은 전송 목적지 IP 주소 뿐이다 .

- 동일 네트워크에 속하는 모든 호스트에 동시 전송 ( 멀티캐스트와의 차이점 ).

- 인터넷상에서는 지역 네트워크내에서만 브로드캐스트를 허용한다 ( 네트워크의 부하를 고려 ).

Page 17: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

17

브로드캐스트 (Broadcast)

2. 주소선택에 따른 브로드캐스트 방식의 구분 .- 지정된 브로드캐스트 : 예 192.12.31.255

- 지역적 브로드캐스트 : 예 255.255.255.255

192 12 31 xxx

네트워크 IP 호스트 IP

192 12 31 255 브로드캐스트 address

255 255 255 255 브로드캐스트 address

Page 18: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

18

Socket Option LayerSocket Option Layer

• level– SOL_SOCKET

• 프로토콜과 무관한 소켓 그 자체

– IPPROTO_IP• IP 에 관련된 옵션

– IPPROTO_TCP• TCP 에 관련된 옵션

Page 19: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

19

IPPROTO_TCPIPPROTO_TCP

• TCP_KEEPALIVE– keep-alive 확인 메시지 전송 시간 지정

• TCP_MAXSEG– TCP 의 MSSS( 최대 메시지 크기 ) 지정

• TCP_NODELAY– Nagle 알고리즘의 선택

Page 20: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

20

Nagle 알고리즘에 대한 이해 .

1. 네트워크상의 패킷 수를 줄이기 위해 제안된 알고리즘 .

2. ACK 를 수신해야만 다음 전송을 진행하는 알고리즘 .

Page 21: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

21

Nagle 알고리즘의 장점과 단점 .

1. 장점 : 네트워크의 효율성이 높아진다 .( 적은 패킷의 양 )

2. 단점 : 전송 속도가 느리다 (ACK 수신 후 패킷 전송 ).

3. 생각해 볼 문제 : Nagle 알고리즘의 중단이 데이터 전송 속도를 무조건

향상시켜 주는 것은 아니다 .

Page 22: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

22

TCP_NODELAY

1. Nagle 알고리즘을 Disable 시키기 위한 옵션의 변경 .

2. TCP 소켓은 생성시 기본적으로 Nagle 알고리즘 적용 .

serv_sock=socket(PF_INET, SOCK_STREAM, 0);

opt_val = TRUE; // #define TRUE 1

setsockopt(serv_sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, sizeof(opt_val));

Page 23: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

23

멀티태스킹멀티태스킹

• 멀티태스킹이란 ?– 사전적 의미

• 한 사람의 사용자가 한 대의 컴퓨터로 2 가지 이상의 작업을 동시에 처리하거나 , 2 가지 이상의 프로그램들을 동시에 실행시키는 것

• 소켓에서의 멀티태스킹– 다중 접속 서버의 구현을 의미

• Fork 을 이용한 멀티 프로세스 , thread 를 이용한 멀티 스레드 기법을 이용하여 하나의 TCP 서버가 다수개의 TCP 클라이언트를 동시에 처리하게 하는 기법

• 소켓에서의 멀티태스킹 기법– fork 를 이용한 멀티태스킹– Thread 를 이용한 멀티태스킹

Page 24: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

24

fork()fork()

• fork()– 자신과 완전히 동일한 코드를 가진 새로운 프로세스를 생성

• 부모프로세스 ( 데이터영역 , 힙 , 스택 ) 를 그대로 복사• 원본 소스의 PC(program counter) 까지 복사를 하기 때문에 새로 생성된

프로세서도 fork() 이후부터 실행– Process

• 리눅스 기반에서 실행되는 모든 프로그램• 각 프로세스는 ID(PID) 라고 불리는 번호를 가지고 있다

– 부모 프로세스 vs 자식 프로세스• 부모 프로세스 : 새로운 프로세스를 호출 (fork) 한 프로세스• 자식 프로세스 : 새롭게 호출된 (forked) 프로세스

• fork 를 이용한 멀티태스킹 시 주의점– 새로 생성된 자식 프로세스와 부모 프로세스는 변수나 메모리를

공유하지 않음 ( 단 외부 파일 , 소켓 등은 공유가능 )– 프로세스 증가로 인한 성능 감소– 변수나 메모리 공유가 필요할 경우 => 스레드 사용

Page 25: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

25

fork() examplefork() example

• fork() 가 호출되면 동일한 프로세스가 두개로 복사되어 실행된다– 부모와 자식 프로세스를 구분하기 위하여 반환값을 검사해야 함

• 부모 프로세스의 fork() 는 자식 프로세스의 process id(pid) 를 리턴• 자식 프로세스의 fork() 는 숫자 0을 리턴• 에러 -> -1

#include <sys/types.h>

#include <unistd.h>

pid_t fork(void); /* 프로세스를 복사 */

#include <unistd.h>

#include <sys/types.h>

pid_t pid; pid=fork(); /* copy new process */ if(pid==0){ /* new process code here */ } else{ /* parent code here */ }

#include <unistd.h>

#include <sys/types.h>

pid_t pid; pid=fork(); /* copy new process */ if(pid==0){ /* new process code here */ } else{ /* parent code here */ }

Page 26: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

26

fork()fork() 를 이용한 다중 클라이언트의 처리를 이용한 다중 클라이언트의 처리

Page 27: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

27

fork()fork() 를 이용한 다중 클라이언트의 처리를 이용한 다중 클라이언트의 처리

pid_t processID;for (;;) {

if(clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0) DieWithError("accept() failed");

if ((processID = fork())<0) DieWithError("fork() failed");

else if (processID == 0) { /* 자식프로세스 : 클라이언트 처리 */close(servSock);

HandleTCPClient(clntSock);exit(0);

}/* 부모 프로세스 : 반복적으로 클라이언트의 접속을 처리 */

}

Page 28: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

28

ThreadThread 를 이용한 멀티태스킹를 이용한 멀티태스킹

• Thread 란 ?– semi process, light weight process– thread 간 메모리 공유

• fork 에 비해서 빠른 프로세스 생성 능력과 적은 메모리를 사용

• Network Programming 에서의 thread– 다중 클라이언트 처리를 위한 서버프로그래밍 작업– 공유변수에서 값을 처리할 경우 사용

• 동기화 문제 어려움 ->쓰기의 경우 mutex 사용

Page 29: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

29

Process Process 와와 ThreadThread

단일 프로세스 멀티 쓰레드

Page 30: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

30

PthreadPthread

• POSIX thread– POSIX 에서 표준으로 제안한 thread 함수 set– POSIX 란 ?

• portable operating system interface• 서로 다른 UNIX OS 의 공통 API 를 정리하여 이식성이 높은 유닉스 응용

프로그램을 개발하기 위한 목적으로 IEEE 가 책정한 애플리케이션 인터페이스 규격

• pthread 실행 순서– pthread create()

• worker(thread) 가 생성

– worker 시작• 각 worker 는 그들의 작업을 실행

– worker 종료• pthread_join() 에 의해서 worker 를 하나로 모음

Page 31: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

31

Thread Thread 생성생성

• pthread_t thread– 생성된 스레드 ID 를 저장할 변수

• pthread_attr_t attr– Set to NULL if default thread attributes are used.

• void * (*start_routine)– pointer to the function to be threaded. – Function has a single argument: pointer to void.

• void *arg– pointer to argument of function

int pthread_create(pthread_t * thread, const pthread_attr_t * attr,void * (*start_routine)(void *), void *arg);

Page 32: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

32

pthread example()pthread example()#include <pthread.h>#include <stdio.h>#include <stdlib.h>#define NUM_THREADS 5

void *PrintHello(void *threadid) { int tid; tid = (int)threadid; printf("Hello World! It's me, thread #%d!\n", tid); pthread_exit(NULL);}

int main(int argc, char *argv[]) {pthread_t threads[NUM_THREADS];int rc, t;for(t=0;t<NUM_THREADS;t++){ printf("In main: creating thread %d\n", t); rc = pthread_create(&threads[t], NULL, PrintHello,

(void *)t); if (rc){ printf("ERROR; return code from pthread_create() is

%d\n", rc); exit(-1); } }pthread_exit(NULL);}

Output

In main: creating thread 0

In main: creating thread 1

Hello World! It's me, thread #0!

In main: creating thread 2

Hello World! It's me, thread #1!

Hello World! It's me, thread #2!

In main: creating thread 3

In main: creating thread 4

Hello World! It's me, thread #3!

Hello World! It's me, thread #4!

Page 33: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

33

pthread()pthread() 를 이용한 다중 클라이언트의 처리를 이용한 다중 클라이언트의 처리

Page 34: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

34

pthread()pthread() 를 이용한 다중 클라이언트의 를 이용한 다중 클라이언트의 처리처리

#include <pthread.h>

pthread_t tid;

void *do_thread(void *arg);

for (;;) {if(clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0)DieWithError("accept() failed");if(pthread_create(&tid, NULL, do_thread, (void *)clntSock) < 0 )

DieWithError(“thread create() failed”);

}

void *do_thread(void *arg) {int csock;csock=(int)arg;HandleTcpClient(csock);pthread_exit(NULL);

}

Page 35: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

35

시그널시그널 (Signal)(Signal)

• 시그널이란 ?– 예상치 않은 이벤트 발생에 따른 일종의 소프트웨어 인터럽트

• Ex) ctrl + c, ctrl + z, 자식 프로세스의 종료– 외부에서 프로세스에게 전달할 수 있는 유일한 통로

• 인터럽트와의 차이점– 인터럽트는 H/W 에 의해 OS 로 전달됨– 시그널은 OS 에 의해 프로세스로 전달됨

• 시그널 값의 확인– /usr/include/signal.h – /usr/include/bits/signum.h

Page 36: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

36

/usr/include/bits/signal.h/usr/include/bits/signal.h#define SIGHUP 1 /* hangup */#define SIGINT 2 /* interrupt , ctrl + c */#define SIGQUIT 3 /* quit */#define SIGILL 4 /* illegal instruction (not reset when caught) */#define SIGTRAP 5 /* trace trap (not reset when caught) */#define SIGIOT 6 /* IOT instruction */#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */#define SIGEMT 7 /* EMT instruction */#define SIGFPE 8 /* floating point exception */#define SIGKILL 9 /* kill (cannot be caught or ignored) */#define SIGBUS 10 /* bus error */#define SIGSEGV 11 /* segmentation violation */#define SIGSYS 12 /* bad argument to system call */#define SIGPIPE 13 /* write on a pipe with no one to read it */#define SIGALRM 14 /* alarm clock */#define SIGTERM 15 /* software termination signal from kill */#if defined(__rtems__)#define SIGURG 16 /* urgent condition on IO channel */#define SIGSTOP 17 /* sendable stop signal not from tty */#define SIGTSTP 18 /* stop signal from tty */#define SIGCONT 19 /* continue a stopped process */#define SIGCHLD 20 /* to parent on child stop or exit */#define SIGCLD 20 /* System V name for SIGCHLD */#define SIGTTIN 21 /* to readers pgrp upon background tty read */#define SIGTTOU 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */#define SIGIO 23 /* input/output possible signal */#define SIGPOLL SIGIO /* System V name for SIGIO */#define SIGWINCH 24 /* window changed */#define SIGUSR1 25 /* user defined signal 1 */#define SIGUSR2 26 /* user defined signal 2 */

Page 37: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

37

커널이 시그널을 처리하는 방법커널이 시그널을 처리하는 방법

• 각 시그널은 시그널 처리기 (signal handler) 를 통해 기본 동작으로 수행– 가능한 기본 동작

• 커널이 시그널을 무시• 사용자에게 통지하지 않고 프로세스를 종료• 프로그램이 인터럽트 되며 시그널 처리 루틴이 실행• 시그널이 블로킹됨

Name Default action DescriptionSIGINT Quit InterruptSIGILL Dump Illegal instructionSIGKILL Quit Kill SIGSEGV Dump Out of range addrSIGALRM Quit Alarm clockSIGCHLD Ignore Child status changeSIGTERM Quit Sw termination sent by kill

Page 38: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

38

시그널 처리 과정시그널 처리 과정

• 시그널 처리 과정1. 시그널이 프로세스로 보내질 때 , OS 는 해당 프로세스를 중지2. 시그널 처리기가 실행되고 내부 루틴이 실행됨3. OS 는 중지되었던 해당 프로세스를 재 실행

Page 39: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

39

sigaction()sigaction() 을 이용한 시그널 처리을 이용한 시그널 처리

• 시그널과 시그널 핸들러를 연결시켜 주는 함수• 특정 시그널에 대한 기본 동작을 바꾸어 준다

• int signo: 시그널 번호• sigaction act: 새로운 동작이 정의된 sigaction• sigaction old: 이전 동작이 저장된 sigaction

#include <signal.h>

int sigaction(int signo, const struct sigaction *act,

struct sigaction *oldact );

struct sigaction

{

void (*sa_handler)( int ); /* 시그널 핸들러 지정 */ sigset_t sa_mask; /* 블록될 시그널 마스킹 */ int sa_flags; /* 시그널의 설정 변경 */ }

Page 40: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

40

sigaction()sigaction() 을 이용한 시그널 처리을 이용한 시그널 처리

/* SIGINT 의 기본동작은 프로그램의 종료이다 . 기본 핸들러를 바꾸어서 종료되지 않고 화면에 문자열을 출력되도록 한다 . */

void handler(int sig);

int main(){ struct sigaction act;act.sa_handler = handler; /* 시그널 핸들러 연결 */sigemptyset( &act.sa_mask ); /* 블록할 시그널 없음 */

act.sa_flags = 0; /* 기본 동작으로 설정 */

sigaction( SIGINT, &act, 0 ); /* SIGINT 과 handler 연결 */

while(1) { printf("Hello World!\n"); sleep(1); }}

void handler(int sig) {printf(“type of signal is %d \n”, sig);

}

Page 41: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

41

타임아웃타임아웃 (SIGALM (SIGALM 시그널시그널 )) 예제예제

• SIGALM 시그널이란 ?– alarm(int) 함수에 의해 발생하며 int 초 이후 발생– 처리기의 기본동작은 프로세스 종료– 이를 수정하여 화면에 문자열 출력

void timer(int sig)  {      puts(“alarm!! \n");   exit(0);    }     int main(int argc, char **argv)   {      struct sigaction act;      act.sa_handler=timer;      sigemptyset(&act.sa_mask);      act.sa_flags=0;            state=sigaction(SIGALRM, &act, 0);         alarm(5);   while(1){        puts(“wait");  sleep(2);      }      return 0;    }

Page 42: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

42

SIGCHLD SIGCHLD 시그널시그널

• SIGCHLD 시그널이란 ?– fork() 로 인해 복제된 프로세스 중 , 자식 프로세스가 종료되면

부모 프로세스에게 전달되는 시그널– fork() 이용시 PTP 프로젝트에 유용

Page 43: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

43

wait() vs waitpid()wait() vs waitpid()

– wait()– 자식프로세스가 반환될 때까지 블럭됨

– waitpid()– WNOHANG 옵션을 이용하면 자식 프로세스가 반환될 때까지 블록 되지 않음

• 시그널의 계류 (pending) 특성으로 인해 SIGCHLD 시그널은 한번 도착했지만 현재 종료된 자식 프로세스는 여러 개 일 수 있다 . 따라서 넌블럭 waitpid 를 반복 호출하여 남아있는 좀비 프로세스의 제거가 가능하다

#include <sys/types.h> #include <sys/wait.h>

pid_t wait(int * status)

#include <sys/types.h> #include <sys/wait.h>

pid_t waitpid(pid_t pid, int * status, int options)

Page 44: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

44

프로세스 분기와 프로세스 분기와 sigactionsigaction 을 이용한 자식 프로세스의 을 이용한 자식 프로세스의 자원수거자원수거

void handler(int sig){ int pid;int status;

  while(1) {    pid = waitpid( WAIT_ANY, &status, WNOHANG );    if ( pid < 0 ) {      perror("waitpid");      break;    }    if ( pid == 0 )      break;  }

}

int main(int argc, char *argv[]){struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;

sigaction(SIGCHLD, &act, 0);pid = fork();

}

Page 45: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

45

넌 블록 넌 블록 I/O I/O 모델모델

Hi..

Hi..

What’s up?

Not much!!

Anyway..

What are you doing?

I’ve just finished network programming assignments

Hi..

Hi..

What’s up?

Not much!!

Anyway..

What are you doing?

I’ve just finished network programming assignments

Client Server

• 다음과 같은 채팅 프로그램의 구현이 가능한지 토의하라

Page 46: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

46

넌 블록 넌 블록 I/O I/O 모델모델

• send() 를 연이어 두 번 하거나 , 클라이언트 혹은 서버 중 어느 한쪽이 먼저 채팅을 시작하게 할 수 있는가 ?

Hi..

Hi..

What’s up?

Not much!!

Anyway..

What are you doing?

I’ve just finished network programming assignments

Client ServerHi..

Hi..

What’s up?

Not much!!

Anyway..

What are you doing?

I’ve just finished network programming assignments

recv()

recv()

recv()

recv()

send()

send()

send()

send()

send()

send()send()

recv()

recv()

recv()

Page 47: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

47

앞 예제의 문제점앞 예제의 문제점

• 사용자의 입출력 패턴과 recv(), send() 의 동기화가 필요함– send() 의 경우 , 사용자 입력이 있을 때까지 기다림– recv() 와 같은 함수의 경우 , 수신할 데이터가 있을 때까지

기다림• 블록 함수

– 동기화 되지 않을 경우 , block 되어 진행 불가

• 사용자의 입력패턴을 정확히 예상하고 send(), recv()를 코딩– 현실적으로 불가능– 한턴씩 진행되는 간단한 경우에 사용가능

Page 48: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

48

해결 방법해결 방법

• 문제점– 블록 함수의 사용으로 인한 고착 상태

• 해결 방안– Non Block 함수의 사용

• 블록 되지 않고 바로 리턴• 필요에 따라 폴링 (polling) 루틴 작성 필요

– 비동기 (Asynchronous I/O) 사용• 소켓 ( 파일 ) 에서 어떤 I/O 변화가 발생하면 그 사실을 응용 프로그램이 알

수 있도록 하여 그 때 원하는 동작을 할 수 있게 하는 모드• I/O 가 발생시 전달되는 SIGIO 처리를 통해 폴링이 아닌 인터럽트 방식으로

처리하는 방식

Page 49: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

49

블록 모드 블록 모드 vs vs 넌블럭 모드넌블럭 모드

• blocking 모드– 어떤 시스템 콜을 호출하였을 때 네트워크 시스템이 동작을

완료할 때까지 그 시스템 콜에서 프로세스가 멈춤• 소켓 생성시 디폴트 blocking 모드

– block 될 수 있는 소켓 시스템 콜• listen(),connect(), accept(), recv(), send(), read(), write(),

recvfrom(), sendto(), close()

– I/O 시 처리가 될 때까지 기다려야 함 . 비 동기적인 작업 수행 불가능

– 일 대 일 통신을 하거나 프로그램이 한가지 작업만 하면 되는 경우는 blocking 모드로 프로그램을 작성할 수 가능

Page 50: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

50

블럭 블럭 vs vs 넌블럭넌블럭

• Non-blocking 모드– 소켓 관련 시스템 콜에 대하여 네트워크 시스템이 즉시 처리할

수 없는 경우라도 시스템 콜이 바로 리턴 되어 응용 프로그램이 block 되지 않게 하는 소켓 모드

– 통신 상대가 여럿이거나 여러 가지 작업을 병행하려면 nonblocking 또는 비동기 모드를 사용하여야 한다 .

• non-blocking 모드를 사용 시 동작 방식– 넌블럭 모드를 사용하는 경우에는 일반적으로 어떤 시스템 콜이

성공적으로 실행될 때까지 계속 루프를 돌면서 주기적으로 확인하는 방법 ( 폴링 ) 을 사용한다 .

Page 51: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

51

Blocking I/O ModelBlocking I/O Model

Application

kernel

recvfromno datagram

readysystem

call

datagram ready

copy datagram

copy completeprocess datagram

process blocks

return OK

Page 52: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

52

Nonblocking I/O ModelNonblocking I/O Model

Application

kernel

recvfrom no datagram ready

system call

datagram ready

copy datagram

copy completeprocess datagram

return OK

EWOULDBLOCK

recvfrom no datagram ready

system callEWOULDBLOCK

recvfromsystem

call

Page 53: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

53

넌블럭 넌블럭 I/OI/O

• 작업이 완료되지 않으면 EWOULDBLOCK(WSAEWOULDBLOC) 를 리턴– 작업이 진행중이라는 뜻으로 에러가 아님

• non-blocking I/O 사용법– Linux

• fcntl(sock_fd, F_SETFL, O_NONBLOCK); // linux – Windows

• unsigned long nb_flag = 1; • ioctlsocket(sock, FIONBIO, &nb_flag); // nb_flag = 0 이면 off

– 모두 polling 을 하여 결과를 확인해야함• while (read(..) == EWOULDBLOCK) {}

Page 54: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

54

비동기 비동기 I/O(I/O( 시그널 인터럽트 방식시그널 인터럽트 방식 ))

• SIGIO 를 이용한 인터럽트 방식– Polling 방식과 대비됨

• 소켓에서 I/O 변화가 발생하면 커널이 이를 응용프로그램에게 알려 원하는 동작을 실행

• 동작 과정1. sigaction() 를 이용 인터럽트 시그널의 종류를 시스템에 알림2. fcntl() 을 이용하여 자신을 소켓의 소유자로 지정3. fcntl() 을 통해 소켓에 FASYNC 플래그를 설정하여 소켓이 비동기 I/O 를 처리하도록 수정

Page 55: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

55

select()select() 를를 이용한 멀티 플렉싱이용한 멀티 플렉싱(Multiplexing)(Multiplexing)• 멀티플렉싱이란 ?

– 다수의 송수신자가 하나의 전송 채널을 공유하는 방식

• 소켓 프로그래밍에서의 멀티플렉싱– 하나의 프로세스를 이용 다수의 송수신 채널을 관리하는 방식– 주로 select() 를 이용하여 처리

• 멀티프로세싱 vs 멀티플렉싱– 다수의 채널을 관리하기 위해 멀티프로세싱이 다수의 프로세스를

사용하는데 비해 멀티플렉싱은 하나의 프로세스내부에서 다수의 채널을 관리

• 용도– 멀티프로세싱 : 동시에 여러 채널의 I/O 가 일어날 경우 , 즉

하나의 프로세스의 종료 기간이 일정시간 지속될 경우– 멀티플렉싱 : 프로세스의 I/O 처리 시간이 짧아 바로 다음

프로세스의 처리가 가능한 경우

Page 56: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

56

멀티플렉싱이란 ?

1. 멀티플렉싱이란 ?- 하나의 전송로를 여러 사용자가 동시에 사용해서 효율성을 극대화 하는 것

고속의 전송로

고속의 전송로

고속의 전송로

고속의 전송로

Page 57: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

57

I/O 멀티플렉싱 기반의 서버

1. I/O 멀티플렉싱이란 ?

- 클라이언트와의 입 /출력을 담당하는 프로세스를 하나로 묶어버리는 형식

- 프로세스가 고속의 전송로에 해당한다 .

Page 58: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

58

멀티 프로세스 vs. 멀티플렉싱

1. 멀티 프로세스 기반의 서버- 클라이언트와 서버간의 송수신 데이터 용량이 큰 경우 .

- 송수신이 연속적으로 발생 하는 경우에 적합 .

2. 멀티플렉싱 기반의 서버- 클라이언트와 서버간의 송수신 데이터 용량이 작은 경우 .

- 송수신이 연속적이지 않은 경우에 적합- 멀티 프로세스 기반의 서버에 비해 많은 수의 클라이언트 처리에 적합 .

Page 59: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

59

I/O Multiplexing Model(Select)I/O Multiplexing Model(Select)

Application

kernel

selectno datagram

readysystem

call

datagram ready

copy datagram

copy completeprocess datagram

process blocks

return OK

recvfrom

return readablesystem

call

process blocks

Page 60: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

60

select 함수의 기능과 호출 순서

1. 지정된 파일 디스크립터의 변화를 확인한다 .- 파일 디스크립터 변화 : 파일 디스크립터를 통해 데이터 송수신 가능한 상태

Page 61: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

61

파일 디스크립터의 변화와 설정 1

1. 파일 디스크립터의 설정 .- 변화를 확인 할 파일 디스크립터를 구분 지어 모아두는 것 ( 총 3 묶음 ).

2. 파일 디스크립터의 변화 .- 수신 할 데이터가 존재하는가 ? ( 입력 버퍼에 데이터 존재 )

- 데이터 전송이 가능한 상태인가 ? ( 출력 버퍼에 충분한 여유공간 존재 )- 소켓에서 예외상황이 발생 하였는가 ? (OOB 메시지 전송 )

3. fd_set 자료형- 파일 디스크립터를 구분 지어 모아두기 위한 자료형 ( 비트단위 배열 )

Page 62: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

62

파일 디스크립터의 변화와 설정 2

함수 선언

FD_ZERO(fd_set * fdset);

FD_SET(int fd, fd_set * fdset);

FD_CLR(int fd, fd_set * fdset);

FD_ISSET(int fd, fd_set * fdset);

Page 63: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

63

검사 범위와 타임 아웃의 설정

1. 검사 해야 할 파일 디스크립터의 범위를 지정해 준다 .- 실제로는 검사해야 하는 파일 디스크립터의 개수를 인자로 전달 . - 가장 큰 파일 디스크립터 값에 1을 더해서 인자로 전달한다 .

2. 타임 아웃을 설정한다 .

struct timeval{ long tv_sec; /* seconds */ long tv_usec; /* microseconds */}

Page 64: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

64

select 함수의 호출 및 결과 확인 1.

#include <sys/time.h> #include <sys/types.h> #include <unistd.h>

int select(int n, fd_set * readfes, fd_set * writefds, fe_set * exceptfds, struct timeval * timeout);

리턴 값 의미

-1 오류 발생

0 타임 아웃

0보다 큰 수 변화 발생 파일 디스크립터 수

Page 65: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

65

select 함수의 호출 및 결과 확인 2

Page 66: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

66

• select()를 활용– 단일 프로세스에서 여러 fd를 모니터링하는 방법을 제공

#include <sys/time.h>#include <sys/types.h>#include <unistd.h>

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

struct timeval { int tv_sec; int tv_usec;};

select()select() 의 활용의 활용

read(recv)를 감지할 fds

write(send)를 감지할 fds

Read, write 검사할 최대 fd+1

Select 가 return될 시간

•0=> 즉시리턴

•Null => blocking

0 : timeout

-1 : error

1 이상 : IO 가 일어난 FD 의 수

Page 67: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

67

// macroFD_ZERO(fd_set *set) - 파일기술자 집합을 소거한다 FD_SET(int fd, fd_set *set) - fd 를 set 에 더해준다FD_CLR(int fd, fd_set *set) - fd 를 set 에서 빼준다

main(void) {fd_set rfds;struct timeval tv;it retval;FD_ZERO(&rfds);FD_SET(0, &rfds);tv.tv_sec=5;tv.tv_usec=0;retval = select(1, &rfds, NULL, NULL, &tv);if(retval) printf(“Data is available now.\n”);else printf(“No data within 5 seconed.\n”);exit(0);

}

시간 내에 IO 의 변화가 있을 경우 , 값을 변경

select() select() 관련 매크로관련 매크로

Page 68: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

68

Select()Select() 를 이용한 키보드 입력과 데이터 수신의 비동기 처리를 이용한 키보드 입력과 데이터 수신의 비동기 처리

select

Start loop

키가 눌렸는가 ?

키보드를 읽어 처리

flag

Socket readable?

flag

Y

N

Loop end

1

0

1

0

소켓을 읽어 처리

Y

N

Page 69: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

69

Select()Select() 를 이용한 키보드 입력과 데이터 수신의 비동기 처리를 이용한 키보드 입력과 데이터 수신의 비동기 처리

FD_ISSET(int fd, fd_set *set) - fd 가 set 안에서 active 한지 확인

int game_end; fd_set readOK;flag=1;

while(1) {FD_ZERO(&readOK);FD_SET(0,&readOK); /* 표준 입력과 소켓의 디스크립터를 세팅 */select(maxfd+1, (fd_set*)&readOK, NULL, NULL, NULL);

if(FD_ISSET(0,&readOK)) {send();…if(game_end) break;

}

if(FD_ISSET(sock, &readOK) {recv(sock, buf, sizeof(buf), 0);…if(game_end) break;

}

Loop 안에 있음을 확인 !

Page 70: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

70

브로드 캐스팅브로드 캐스팅

• 브로드캐스트란 ?– LAN 전체에 데이터를 뿌리는 전송 방식

• 네트워크 부하를 줄이기 위해 브로드캐스팅은 LAN 으로 제한된다 .

• 브로드캐스팅 전송 방식– 서브넷 직접 전송

• 특정 서브넷의 모든 호스트에 전송• e.g.) 203.252.153.255 // 203.252.153.0 네트워크의 모든 호스트에게

전송

– 제한된 브로드캐스팅• 전송 호스트가 속한 LAN 의 모든 호스트에게 전송• e.g) 255.255.255.255• 라우터는 해당 패킷을 전달하지 않음

Page 71: 얇지만 얇지 않은  TCP/IP  소켓 프로그래밍  C 2 판

71

브로드캐스팅 방법브로드캐스팅 방법

• 브로드캐스팅은 UDP 만 지원• 수신자는 수정사항 없으며 송신자는 아래와 같은 약간의

수정내용 필요

/* 서버 주소 구조체 초기화 시 주소를 브로드캐스팅 주소로 설정 */SOCKADDR_IN serv;memset(&remoteaddr, 0, sizeof(remoteaddr));serv.sin_family = AF_INET;serv.sin_port = htons(9000);serv.sin_addr.s_addr = htonl(INADDR_BROADCAST);……

/* 소켓을 브로드캐스팅이 가능토록 설정 */int broadcastPerm = 1;if (setsockopt(sock,SOL_SOCKET, SO_BROADCAST, $broadcastPerm, sizeof(broadcastPerm)) < 0)

/* 서버 주소 구조체 초기화 시 주소를 브로드캐스팅 주소로 설정 */SOCKADDR_IN serv;memset(&remoteaddr, 0, sizeof(remoteaddr));serv.sin_family = AF_INET;serv.sin_port = htons(9000);serv.sin_addr.s_addr = htonl(INADDR_BROADCAST);……

/* 소켓을 브로드캐스팅이 가능토록 설정 */int broadcastPerm = 1;if (setsockopt(sock,SOL_SOCKET, SO_BROADCAST, $broadcastPerm, sizeof(broadcastPerm)) < 0)