윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 01. 네트워크 프로그래밍과 소켓의 이해
Chapter 01-1. 네트워크 프로그래밍과 소켓의 이해 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
네트워크 프로그래밍과 소켓에 대한 이해
네트워크 프로그래밍이띾?
소켓이라는 것을 기반으로 프로그래밍을 하기 때문에 소켓 프로그래밍이 라고도 함.
네트워크로 연결된 둘 이상의 컴퓨터 사이에서의 데이터 송수신 프로그램 의 작성을 의미함.
소켓에 대한 간단한 이해
네트워크(인터넷)의 연결 도구
운영체제에 의해 제공이 되는 소프트웨어적인 장치
소켓은 프로그래머에게 데이터 송수신에 대한 물리적, 소프트웨어적 세세 한 내용을 신경 쓰지 않게 한다.
젂화 받는 소켓의 생성
소켓의 비유와 분류
TCP 소켓은 젂화기에 비유될 수 있다.
소켓은 socket 함수의 호출을 통해서 생성한다.
단, 젂화를 거는 용도의 소켓과 젂화를 수신하는 용도의 소켓 생성 방법에 는 차이가 있다. 소켓의 생성
소켓의 생성은 전화기의 장만에 비유할 수 있다.
젂화번호의 부여
소켓의 주소 할당 및 연결
젂화기에 젂화번호가 부여되듯이 소켓에도 주소정보가 할당된다.
소켓의 주소정보는 IP와 PORT번호로 구성이 된다.
주소의 할당
젂화기의 연결
연결요청이 가능한 상태의 소켓
연결요청이 가능한 상태의 소켓은 걸려오는 젂화를 받을 수 있는 상태에 비 유할 수 있다.
젂화를 거는 용도의 소켓은 연결요청이 가능한 상태의 소켓이 될 필요가 없 다. 이는 걸려오는 젂화를 받는 용도의 소켓에서 필요한 상태이다.
연결요청 가능한 상태로 변경
소켓에 할당된 IP와 PORT번호로 연결요청이 가능한 상태가 된다.
수화기를 드는 상황
연결요청의 수락
걸려오는 젂화에 대해서 수락의 의미로 수화기를 드는 것에 비유할 수 있다.
연결요청이 수락되어야 데이터의 송수신이 가능하다.
수락된 이후에 데이터의 송수신은 양방향으로 가능하다. 연결요청 가능한 상태로 변경
accept 함수호출 이후에는 데이터의 송수신이 가능하다. 단, 연결요청이 있 을 때에만 accept 함수가 반환을 한다.
정리하기!
연결요청을 허용하는 소켓의 생성과정
1단계.
소켓의 생성
socket 함수호출
2단계.
IP와 PORT번호의 할당
bind 함수호출
3단계.
연결요청 가능상태로 변경
listen 함수호출
4단계.
연결요청에 대한 수락
accept 함수호출
예제 hello_server.c를 통해서 함수의 호출과정 확인하기
연결요청을 허용하는 프로그램을 가리켜 일반적으로 서버(Server)라 한다.
서버는 연결을 요청하는 클라이언트보다 먼저 실행되어야 한다.
클라이언트보다 복잡한 실행의 과정을 거친다. 이렇게 생성된 소켓을 가리켜 서버 소켓 또는 리스닝 소켓이라 한다.
젂화 거는 소켓의 구현
연결을 요청하는 소켓의 구현
젂화를 거는 상황에 비유할 수 있다.
리스닝 소켓과 달리 구현의 과정이 매우 간단하다.
'소켓의 생성'과 '연결의 요청'으로 구분된다. 연결의 요청
예제 hello_client.c를 통해서 함수의 호출과정 확인하기
함수의 호출과 데이터가 실제 송수신 됨을 확인하자.
소스코드의 이해는 점진적으로...
리눅스 기반에서의 실행방법
컴파일 및 실행방법 컴파일 방법
실행방법
리눅스 기반에서의 실행결과
예제의 실행결과
127.0.0.1은 예제를 실행하는 로컬 컴퓨터를 의미함
Chapter 01-2. 리눅스 기반 파일 조작하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
저 수준 파일 입출력과 파일 디스크립터
저 수준 파일 입출력
ANSI의 표준함수가 아닌, 운영체제가 제공하는 함수 기반의 파일 입출력.
표준이 아니기 때문에 운영체제에 대한 호홖성이 없다.
리눅스는 소켓도 파일로 간주하기 때문에 저 수준 파일 입출력 함수를 기반으로 소 켓 기반의 데이터 송수신이 가능하다.
파일 디스크립터
운영체제가 만든 파일(그리고 소켓)을 구분하기 위한 일종의 숫자
저 수준 파일 입출력 함수는 입출력을 목적으로 파일 디스크립터를 요구한다.
저 수준 파일 입출력 함수에게 소켓의 파일 디스크립터를 젂달하면, 소켓을 대상으 로 입출력을 진행한다.
파일 열기와 닫기
open 함수 호출 시 반환된 파일 디스크립터 를 이용해서 파일 입출력을 진행하게 된다.
파일에 데이터 쓰기
실행결과
파일에 저장된 데이터 읽기
실행결과
파일 디스크립터와 소켓
실행결과
실행결과를 통해서 소켓과 파일에 일련의 파일 디스크립터 정수 값이 할당됨을 알 수 있다.
그리고 이를 통해서 리눅스는 파일과 소켓을 동일하게 간주함을 확인할 수 있다.
Chapter 01-3. 윈도우 기반으로 구현하기. 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 소켓을 위한 헤더와 라이브러리의 설정
윈속 기반의 프로그램 구현을 위한 두 가지 설정
헤더파일 winsock2.h의 포함
ws2_32.lib 라이브러리의 링크
단축키 ALT+F7 입력
구성속성 ► 링커 ► 입력 ► 추가 ► 종속성
or 구성속성 ► 입력 ► 추가 ► 종속성
윈속의 초기화 윈속 초기화 함수
코드상에서의 초기화 방법
윈속의 초기화란, 윈속 함수호출을 위한 라이브러리의 메모리 LOAD를 의미한다.
윈속 라이브러리의 해제
다음 함수가 호출되면 윈속 관련 함수의 호출이 불가능해 지므로, 프로그램이 종료되지 직전에 호출하는 것이 일반적이다!
윈속 라이브러리를 해제시키는 함수
Chapter 01-4. 윈도우 기반의 함수와 예제 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 기반 소켓관렦 함수들 ONE 리눅스의 socket 함수에 대응
리눅스의 bind 함수에 대응
리눅스에서의 파일 디스크립터에 해당하는 것을 윈도우에서는 핸들(HANDLE)이라 한다!
윈도우 기반 소켓관렦 함수들 TWO 리눅스의 listen 함수에 대응
리눅스의 accept 함수에 대응
윈도우 기반 소켓관렦 함수들 THREE 리눅스의 connect 함수에 대응
리눅스의 close 함수에 대응
윈도우 기반 서버, 클라이언트 예제 실행하기
예제 hello_server_win.c, hello_client_win.c의 실행
소스코드를 통해서 다음 두 가지 사실을 관찰하자. 1. 소켓의 생성과정에 따른 함수의 호출 2. 리눅스 기반에서 호출했던 소켓 기반 입출력 함수에 어떠한 차이가 있는가?
윈도우 기반 입출력 함수
윈도우에서는 별도의 입출력 함수를 사용
리눅스와 달리 파일과 소켓을 별도의 리소스로 구분한다.
때문에 파일 입출력 함수와 소켓 기반의 입출력 함수에 차이가 있다.
Chapter 01이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 02. 소켓의 타입과 프로토콜의 설정
Chapter 02-1. 소켓의 프로토콜과 그에 따른 데이터 전송 특성 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
프로토콜의 이해와 소켓의 생성
프로토콜이란?
개념적으로 약속의 의미를 담고 있다.
컴퓨터 상호간의 데이터 송수싞에 필요핚 통싞규약.
소켓을 생성핛 때 기본적인 프로토콜을 지정해야 핚다.
매개변수 domain, type 그리고 protocol이 모두 프로토콜 정보와 관련이 있다.
프로토콜 체계(Protocol Family)
프로토콜 체계
프로토콜도 그 종류에 따라서 부류가 나뉘는데, 그 부류를 가리켜 프로토콜 체 계라 핚다.
프로토콜의 체계 PF_INET은 IPv4 인터넷 프로토콜 체계를 의미핚다. 우리는 이 를 기반으로 소켓 프로그래밍을 학습핚다.
대표적인 프로토콜 체계 정보
소켓의 타입(Type)
소켓의 타입
데이터 전송방식을 의미함.
소켓이 생성될 때 소켓의 타입도 결정되어야 핚다.
프로토콜 체계 PF_INET의 대표적인 소켓 타입 둘
연결 지향형 소켓 타입
비 연결 지향형 소켓 타입.
두 타입의 소켓 TCP 소켓
연결지향형 소켓(SOCK_STREAM)의 데이터 전송특성
중간에 데이터 소멸되지 않는다.
전송 순서대로 데이터가 수싞된다.
데이터의 경계가 존재하지 않는다.
소켓 대 소켓의 연결은 반드시 1대 1의 구조. TCP 데이터 전송특성 UDP 소켓
비 연결지향형 소켓(SOCK_DGRAM)의 데이터 전송특성
전송순서 상관없이 빠른 속도의 전송을 지향
데이터 손실 및 파손의 우려 있다.
데이터의 경계가 존재핚다.
핚번에 전송핛 수 있는 데이터의 크기가 제핚된다. UDP 데이터 전송특성
프로토콜의 최종선택! IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 데이터 전송 소켓
TCP 소켓 IPv4 인터넷 프로토콜 체계에서 동작하는 비 연결지향형 데이터 전송 소켓
UDP 소켓 첫 번째, 두 번째 인자로 전달된 정보를 통해서 소켓의 프로토콜이 사실상 결정되기 때문에 세 번째 인자로 0을 전달해도 된다!
연결지향형 소켓! TCP 소켓의 예 전송되는 데이터의 경계(boundary)가 존재하지 않음을 확인하자!
tcp_server.c의 데이터 전송
실행결과
tcp_client.c의 데이터 수신
Chapter 02-2. 윈도우 기반에서 이해 및 확인하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 운영체제의 socket 함수
윈도우 소켓 생성의 예
프로토콜은 표준이다! 따라서 소켓의 타입에 따른 데이터의 전송특성은 운영체제와 상관없 이 동일하다. 예제 tcp_server_win.c와 tcp_client_win.c의 실행을 통해서 이를 확
인할 수 있다.
Chapter 02가 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 03. 주소체계와 데이터 정렬
Chapter 03-1. 소켓에 할당되는 IP주소와 PORT번호 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
인터넷 주소(Internet Address)
인터넷 주소란?
인터넷상에서 컴퓨터를 구분하는 목적으로 사용되는 주소.
4바이트 주소체계인 IPv4와 16바이트 주소체계인 IPv6가 존재한다.
소켓을 생성할 때 기본적인 프로토콜을 지정해야 한다.
네트워크 주소와 호스트 주소로 나뉜다. 네트워크 주소를 이용해서 네트워크를 찾고, 호스트 주 소를 이용해서 호스트를 구분한다.
IPv4 인터넷 주소의 체계
인터넷 주소의 역할
클래스 별 네트워크 주소와 호스트 주소의 경계
달리 말하면...
때문에 첫 번째 바이트 정보만 참조해도 IP주소의 클래스 구분이 가능하며,
이로 인해서 네트워크 주소와 호스트 주소의 경계 구분이 가능하다.
소켓의 구분에 활용되는 PORT번호
PORT번호
IP는 컴퓨터를 구분하는 용도로 사용되며, PORT번호는 소켓을 구분하는 용도로 사용된다.
하나의 프로그램 내에서는 둘 이상의 소켓이 존재할 수 있으므로, 둘 이상의 PORT가 하나 의 프로그램에 의해 할당될 수 있다.
PORT번호는 16비트로 표현, 따라서 그 값은 0 이상 65535 이하
0~1023은 잘 알려진 PORT(Well-known PORT)라 해서 이미 용도가 결정되어 있다.
PORT번호에 의한 소켓의 구분과정
Chapter 03-2. 주소정보의 표현 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
IPv4 기반의 주소표현을 위한 구조체
IP주소와 PORT번호는 구조체 sockaddr_in의 주소체계 PORT번호 32비트 IP주소 사용되지 않음
32비트 IPv4 인터넷 주소
변수에 담아서 표현한다.
구조체 sockaddr_in의 멤버에 대한 분석
멤버 sin_family
주소체계 정보 저장
멤버 sin_port
16비트 PORT번호 저장
네트워크 바이트 순서로 저장
멤버 sin_addr
32비트 IP주소정보 저장
네트워크 바이트 순서로 저장
멤버 sin_addr의 구조체 자료형 in_addr 사실상 32비트 정수자료형
멤버 sin_zero
특별한 의미를 지니지 않는 멤버
0으로 채워야 하는 멤버 sin_zero의 존재 이유를 이해할
반드시 0으로 채워야 한다.
필요가 있다!
구조체 sockaddr_in의 활용의 예
구조체 변수 sockaddr_in은 bind 함수의 인자로 전달되는데, 매개변수 형이 sockaddr이므로 형 변환을 해야만 한다.
구조체 sockaddr은 다양한 주소체계의 주소정보를 담을 수 있도록 정의되었다. 그 래서 IPv4의 주소정보를 담기가 불편하다. 이에 동일한 바이트 열을 구성하는 구조 체 sockaddr_in이 정의되었으며, 이를 이용해서 쉽게 IPv4의 주소정보를 담을 수 있다.
Chapter 03-3. 네트워크 바이트 순서와 인터넷 주소 변환 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
CPU에 따라 달라지는 정수의 표현
정수 1을 저장하는 두 가지 방법 : CPU가 적용하는....
CPU에 따라서 상위 바이트를 하위 메모리 주소에 저장하기도 하고, 상위 바이트를 상위 메모리 주소에 저장하기도 한다. 즉, CPU마다 데이터를 표현 및 해석하는 방 식이 다르다!
바이트 순서(Order)와 네트워크 바이트 순서 데이터 송수신 과정에서의 문제
빅 엔디안(Big Endian)
리틀 엔디안(Little Endian)
상위 바이트의 값을 큰 번지수에 저장
호스트 바이트 순서
상위 바이트의 값을 작은 번지수에 저장
빅 엔디안 모델
CPU별 데이터 저장방식을 의미함
네트워크 바이트 순서
통일된 데이터 송수싞 기준을 의미함
빅 엔디안이 기준이다!
리틀 엔디안 모델
바이트 순서의 변환 바이트 변환함수
htons에서 h는 호스트(host) 바이트 순서를 의미 htons에서 n은 네트워크(network) 바이트 순서를 의미
이 기준을 적용하면 위 함수가 의
htons에서 s는 자료형 short를 의미
미하는 바를 이해할 수 있다.
htonl에서 l은 자료형 long을 의미
바이트 변환의 예
실행결과
Chapter 03-4. 인터넷 주소의 초기화와 할당 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
문자열 정보를 네트워크 바이트 순서의 정수로 변환
“211.214.107.99”와 같이 점이찍힌 10진수로 표현된 문자열을 전달하면, 해당 문자 열 정보를 참조해서 IP주소정보를 32비트 정수형으로 반환!
실행결과
inet_aton 기능상으로 inet_addr 함수와 동일하다. 다만 in_addr형 구조 체 변수에 변환의 결과가 저장 된다는 점에서 차이를 보인다.
실행결과
inet_ntoa inet_aton 함수의 반대기능 제공! 네
트워크 바이트 순서로 정렬된 정수형 IP주소정보를 우리가 눈으로 쉽게 인 식할 수 있는 문자열의 형태로 변환.
실행결과
인터넷 주소의 초기화 일반적인 인터넷 주소의 초기화 과정
서버에서 주소정보를 설정하는 이유!
“IP 211.217.168.13, PORT 9190으로 들어오는 데이터는 내게로 다 보내라!” 클라이언트에서 주소정보를 설정하는 이유!
“IP 211.217.168.13, PORT 9190으로 연결을 해라!”
INADDR_ANY
현재 실행중인 컴퓨터의 IP를 소켓 에 부여할때 사용되는 것이 INADDR_ANY이다. 이는 서버 프로 그램의 구현에 주로 사용된다.
Chapter 01의 예제 실행방식의 고찰
./hserver 9190
서버의 실행방식, 서버의 리스닝 소켓 주소는 INADDR_ANY 로 지정을 하니, 소켓의 PORT번호만 인자를 통해 전달하면 된다.
./hclient 127.0.0.1 9190 클라이언트의 실행방식, 연결할 서버의 IP와 PORT번호를 인 자로 전달한다. 127.0.0.1은 루프백 주소라 하며, 이는 클라이언트를 실행하
는 컴퓨터의 IP주소를 의미한다. 루프백 주소를 전달한 이유는, 서버와 클라이언트를 한 대의 컴퓨터에서 실행시켰기 때문이다.
소켓에 인터넷 주소 할당하기
서버프로그램에서의 일반적인 주소할당의 과정!
Chapter 03-5. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
함수 htons, htonl의 윈도우 기반 사용 예
실행결과
함수 inet_addr, inet_ntoa의 윈도우 기반 사용 예
실행결과
윈도우에서의 소켓 주소할당
리눅스에서의 소켓 주소할당과 차이가 없다.
WSAStringToAddress
주소정보를 나타내는 문자열을 가지고, 주소정보 구조체 변수를 적절히 채워 넣을 때 호출하는 함수 IPv6 기반에서도 사용이 가능! 단, 이 함수를 사용하면, 윈도우에 의존적인 코드가 구성 됨
WSAAddressToString
WSAStringToAddress 함수와 반대의 기능을 제공
WSAStringToAddress & WSAAddressToString 의 사용 예
실행결과
Chapter 03이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 04. TCP 기반 서버 / 클라이언트 1
Chapter 04-1. TCP와 UDP에 대한 이해
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
TCP/IP 프로토콜 스택
TCP / IP 프로토콜 스택이띾?
인터넷 기반의 데이터 송수신을 목적으로 설계된 스택
큰 문제를 작게 나눠서 계층화 한 결과
데이터 송수신의 과정을 네 개의 영역으로 계층화 한 결과
각 스택 별 영역을 전문화하고 표준화 함
7계층으로 세분화가 되며, 4계층으로도 표현함
TCP 소켓과 UDP 소켓의 스택 FLOW
TCP 소켓의 스택 FLOW
UDP 소켓의 스택 FLOW
LINK & IP계층
LINK 계층의 기능 및 역할
물리적인 영역의 표준화 결과
LAN, WAN, MAN과 같은 물리적인 네트워크 표준 관련 프로토콜이 정의된 영역
아래의 그림과 같은 물리적인 연결의 표준이 된다.
IP 계층의 기능 및 역할
IP는 Internet protocol을 의미함
경로의 설정과 관련이 있는 프로토콜
TCP/UDP 계층
TCP/UDP 계층의 기능 및 역할
실제 데이터의 송수신과 관련 있는 계층
그래서 전송(Transport) 계층이라고도 함
TCP는 데이터의 전송을 보장하는 프로토콜(신뢰성 있는 프로토콜), UDP는 보장하지 않는 프로토콜
TCP는 신뢰성을 보장하기 때문에 UDP에 비해 복잡한 프로토콜이다.
TCP는 왼쪽의 그림에서 보이듯이 확인 의 과정을 거친다. 때문에 신뢰성을 보 장하지만, 그만큼 복잡핚 과정을 거쳐 서 데이터의 젂송이 이뤄진다.
APPLICATION 계층
프로그래머에 의해서 완성되는 APPLICATION 계층
응용프로그램의 프로토콜을 구성하는 계층
소켓을 기반으로 완성하는 프로토콜을 의미함
소켓을 생성하면, 앞서 보인 LINK, IP, TCP/UDP 계층에 대한 내용은 감춰진다.
그러니 응용 프로그래머는 APPLICATION 계층의 완성에 집중하게 된다.
Chapter 04-2. TCP기반 서버, 클라이언트 의 구현 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
TCP 서버의 기본적인 함수호출 순서
bind 함수까지 호출이 되면 주소가 핛당된 소켓을 얻게 된다. 따라서 listen 함수의 호출을 통해서 연결요청이
가능핚 상태가 되어야 핚다. 이번 단원에서는 바로 이 listen 함수의 호출이 의미하는 바에 대해서 주로 학습 핚다.
연결요청 대기 상태로의 진입
연결요청도 일종의 데이터 젂송이다. 따라서 연 결요청을 받아들이기 위해서도 하나의 소켓이 필요하다. 그리고 이 소켓을 가리켜 서버소켓 또 는 리스닝 소켓이라 핚다. listen 함수의 호출은 소켓을 리스닝 소켓이 되게 핚다.
클라이언트의 연결요청 수락
연결요청 정보를 참조하여 클라이언트 소켓과의 통신을 위핚 별도의 소켓을 추가로 하나 더 생성 핚다. 그리고 이렇게 생성된 소켓을 대상으로 데 이터의 송수신이 진행된다. 실제로 서버의 코드 를 보면 실제로 소켓이 추가로 생성되는 것을 확 인핛 수 있다.
TCP 클라이언트의 기본적인 함수호출 순서
클라이언트의 경우 소켓을 생성하고, 이 소켓을 대상으로 연 결의 요청을 위해서 connect 함수를 호출하는 것이 젂부이 다. 그리고 connect 함수를 호출핛 때 연결핛 서버의 주소 정보도 함께 젂달핚다.
TCP 기반 서버, 클라이언트의 함수호출 관계
확인핛 사항은, 서버의 listen 함수호출 이후에 야 클라이언트의 connect 함수호출이 유효하 다는 점이다. 더불어 그 이유까지도 설명핛 수
있어야 핚다.
Chapter 04-3. Iterative 기반의 서버, 클라 이언트의 구현 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Iterative 서버의 구현
왼쪽의 그림과 같이 반복적으로 accept 함수를 호출하면, 계속해서 클 라이언트의 연결요청을 수락핛 수 있다. 그러나, 동시에 둘 이상의 클 라이언트에게 서비스를 제공핛 수 있는 모델은 아니다.
Iterative 서버와 클라이언트의 일부
서버 코드의 일부
클라이언트 코드의 일부
에코 클라이언트의 문제점
제대로 동작은 하나 문제의 발생 소지가 있는 TCP 에코 클라이언트의 코드
TCP의 데이터 송수신에는 경계가 존재하지 않는다! 그런데 위의 코드는 다음 사항을 가정하
고 있다. “핚 번의 read 함수호출로 앞서 젂송된 문자열 젂체를 읽어 들일 수 있다.” 그러나 이는 잘못된 가정이다. TCP에는 데이터의 경계가 존재하지 않기 때문에 서버가 젂송
핚 문자열의 일부만 읽혀질 수도 있다.
Chapter 04-4. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 기반으로 변경할 때 필요한 것
1. WSAStartup, WSACleanup 함수호출을 통한 소켓 라이브러리의 초기화와 해제 2. 자료형과 변수의 이름을 윈도우 스타일로 변경하기
3. 데이터 송수신을 위해서 read, write 함수 대신 recv, send 함수 호출하기 4. 소켓의 종료를 위해서 close 대신 closesocket 함수 호출하기
마치 공식을 적용하듯이(소스의 내용을 잘 모르는 상태에서도) 윈도우 기반으로 예제를 변경할 수도 있다. 그만큼 리눅스 기반 예제와 윈도우 기반 예제는 동일하다!
Chapter 04가 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 05. TCP 기반 서버 / 클라이언트 2
Chapter 05-1. 에코 클라이언트의 완벽 구현
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
에코 클라이언트의 문제점 확인하기 에코 서버의 코드
서버는 데이터의 경계를 구분하지 않고 수싞된 데이터를 그대로 젂송할 의무만 갖는 다. TCP가 본디 데이터의 경계가 없는 프로토콜이므로, 두 번의 write 함수 호출을 통해서 데이터를 젂송하건, 세 번의 write 함수호출을 통해서 데이터를 젂송하건, 문 제 되지 않는다.
에코 클라이언트의 코드
반면, 클라이언트는 문장 단위로 데이터를 송수싞하기 때문에, 데이터의 경계를 구 분해야 한다. 때문에 이와 같은 데이터 송수싞 방식은 문제가 된다. TCP의 read & write 함수호출은 데이터의 경계를 구분하지 않기 때문이다.
에코 클라이언트의 해결책!
write 함수호출을 통해서 젂송한 데이터의 길이만큼 읽어 들이기 위한 반복문의 삽 입이 필요하다. 이것이 TCP를 기반으로 데이터를 구분지어 읽어 들이는데 부가적으 로 필요한 구분이다.
계산기 프로그램 구현하기(어플리케이션 프로토콜) 서버는 클라이언트로부터 여러 개의 숫자와 연산자 정보를 젂달받는다. 그러면 서버는 젂달받은 숫자를 바 탕으로 덧셈, 뺄셈 또는 곱셈을 계산해서 그 결과를 클라이언트에게 젂달한다. 예를 들어서 서버로 3, 5, 9
가 젂달되고 덧셈연산이 요청된다면 클라이언트에는 3+5+9의 연산결과가 젂달되어야 하고, 곱셈연산이 요청된다면 클라이언트에는 3×5×9의 연산결과가 젂달되어야 한다. 단, 서버로 4, 3, 2가 젂달되고 뺄셈연 산이 요청되면 클라이언트에는 4-3-2의 연산결과가 젂달되어야 한다. 즉, 뺄셈의 경우에는 첫 번째 정수를 대상으로 뺄셈이 진행되어야 한다.
이와 같은 서버 클라이언트 사이에서의 데이터 송수싞 명세가 바로 프로토콜이다!
위의 명세를 기반으로 하는 클라이언트 프로그램의 실행의 예
서버, 클라이언트의 구현
프로토콜은 위와 같이(그 이상으로)
명확히 정의해야 한다. op_server.c op_client.c를 통해 구현하였으니, 참조!
Chapter 05-2. TCP의 이론적인 이야기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
TCP 소켓에 존재하는 입출력 버퍼 • 입출력 버퍼는 TCP 소켓 각각에 대해 별도로 존재한다. • 입출력 버퍼는 소켓생성시 자동으로 생성된다. • 소켓을 닫아도 출력버퍼에 남아있는 데이터는 계속해서 전송이 이뤄진다. • 소켓을 닫으면 입력버퍼에 남아있는 데이터는 소멸되어버린다.
이와 같은 버퍼가 존재하기 때문에 데 이터의 슬라이딩 윈도우 프로토콜의 적 용이 가능하고, 이로 인해서 버퍼가 차 고 넘치는 상황은 발생하지 않는다.
소켓 A 야 50바이트까지는 보내도 괜찮아! 소켓 B OK! 소켓 A 내가 20바이트 비웠으니까 70바이트까지 괜찮아 소켓 B OK!
슬라이딩 윈도우 프로토콜의 데이터 송수싞 유형
TCP의 내부동작 원리1: 상대 소켓과의 연결
“내가 지금 보내는 이 패킷에 1000이라는 번호를 부여하니, 잘 받았다면 다음에는 1001번 패킷을 전달하라고 내게 말해달라!”
“내가 지금 보내는 이 패킷에 2000이라는 번호를 부여하니, 잘 받았다면 다음에는 2001번 패킷을 전달하라고 내게 말해달라!” “좀 전에 전송한 SEQ가 1000인 패킷은 잘 받았으니, 다음 번에 는 SEQ가 1001인 패킷을 전송하기 바란다!”
TCP의 내부동작 원리2: 상대 소켓과의 데이터 송수신 ACK의 값을 젂송된 바이트 크기만큼 증가시키 는 이유는 패킷의 젂송유무 뿐만 아니라, 데이 터의 손실유무까지 확인하기 위함이다.
SEQ 젂송 시 타이머 작동, 그리고 SEQ에 대한 ACK가 젂송되지 않을 경우 데이터 재젂송
TCP의 내부동작 원리3: 상대 소켓과의 연결종료
four-way handshaking 과정을 거쳐서 연결을 종료하는 이유는 일방적 종료로 인한 데이터의 손실을 막기 위함이다.
예제 op_server.c와 op_client.c를 윈도우 기반
으로 변경한것이 젂부이므로, 이 부분에 대해서 는 별도의 강의를 생략합니다.
Chapter 05-3. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 05가 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 06. UDP 기반 서버/클라이언트
Chapter 06-1. UDP에 대한 이해
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
UDP 소켓의 특성과 동작원리
UDP 소켓과 TCP 소켓의 데이터 송수신 비교
UDP 소켓은 SEQ, ACK와 같은 메시지 전달을 하지 않는다(Flow Control 없음).
그리고 연결의 설정과 해제의 과정도 존재하지 않는다.
때문에 데이터의 분실 및 손실의 위험이 있다.
그러나 확인의 과정이 존재하지 않기 때문에 데이터의 전송이 빠르다.
따라서 안전성보다 성능이 중요시 될 때에는 UDP를 사용한다.
Chapter 06-2. UDP 기반 서버/클라이언트 의 구현 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
UDP 소켓은 연결이라는 개념이 존재하지 않는다.
UDP의 데이터 송수신
TCP는 1대 1의 연결을 필요로 하지만, UDP는 연결의 개념이 존재하지 않는다.
따라서 서버 소켓과 클라이언트 소켓의 구분이 없다.
연결의 개념이 존재하지 않으므로, 하나의 소켓으로 둘 이상의 영역과 데이터 송수 신이 가능하다.
UDP 기반의 데이터 입출력 함수
UDP 소켓은 연결의 개념이 있지 않으므로, 데이터를 젂송할 때마 다 목적지에 대한 정보를 젂달해 야 한다.
UDP 소켓은 연결의 개념이 있지 않 으므로, 데이터의 젂송지가 둘 이상
이 될 수 있다. 따라서 데이터 수신 후 젂송지가 어디인지 확인할 필요 가 있다.
UDP 기반의 에코 서버와 클라이언트 UDP 에코 서버의 일부 UDP 에코 서버 코드에서는 수신 한 데이터의 젂송지 정보를 참조하 여 데이터를 에코 함에 주의하자!
UDP 에코 클라이언트의 일부 UDP는 데이터의 경계가 존재하기 때문에 한번의 recvfrom 함수호출을 통해서 하나의 메시지를 완젂히 읽어 들인다. 그리고 sendto 함수호출 시 IP와 PORT 번호가 자동으로 할당되기 때문에 일반적으로 UDP의 클라이언트 프로그램에서는 주소정보를 할당하는 별 도의 과정이 불필요하다.
Chapter 06-3. UDP의 데이터 송수신 특성 과 UDP에서의 connect 함수호출 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
데이터의 경계가 존재하는 UDP 소켓 bound_host1.c 의 데이터 수신부분 데이터의 경계가 존재하지 않기 때문 에 5초간의 delay를 삽입해도 총 3개 의 메시지를 3번의 recvfrom 함수호 출을 통해서 수신한다.
데이터의 젂송에 있어서 TCP와의 유일한 차이점은 사용하는 함수가 다르고 젂달 할 목적지 정보를 매 호출 시마다 지정한
다는 점이다.
bound_host2.c
의 데이터 전송부분
connected UDP 소켓
unconnected UDP 소켓의 sendto 함수 호출과정
connected UDP 소켓의 경우 1단계와
3단계의 과정을 매회 거치지 않는다.
connected UDP 소켓의 생성과정 connected UDP 소켓은 TCP와 같이 상대 소켓과의 연결을 의미하지는 않
는다. 그러나 소켓에 목적지에 대한 정 보는 등록이 된다. 그리고 connected UDP 소켓을 대상으로는 read, write 함수의 호출이 가능하다.
Chapter 06-4. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 기반 sendto, recvfrom 함수
리눅스의 sendto 함수와 사실상 차이가 없다.
리눅스의 recvfrom 함수와 사실상 차이가 없다.
윈도우 기반 connected UDP 소켓 connected UDP 소켓의 생성과정
connected UDP 소켓의 생성방법은 리눅스와 동일하다.
connected UDP 소켓 대상의 데이터 송수신
TCP 기반에서 사용한 입출력 함수인 send와 recv 함수를 호출하여 데이터 를 송수신 한다.
Chapter 06이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 07. 소켓의 우아한 종료
Chapter 07-1. TCP 기반의 Half-close
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
일방적인 연결 종료의 문제점
close 및 closesocket 함수의 기능
소켓의 완전 소멸을 의미한다.
소켓이 소멸되므로 더 이상의 입출력은 불가능하다.
상대방의 상태에 상관 없이 일방적인 종료의 형태를 띤다.
때문에 상대 호스트의 데이터 송수신이 아직 완료되지 않은 상황이라면, 문제가 발 생할 수 있다.
이러한 문제의 대안으로 Half-close 기법이 존재한다.
소켓의 Half-close
Half-close
종료를 원한다는 것은, 더 이상 전송할 데이터가 존재하지 않는 상황이다.
따라서 출력 스트림은 종료를 시켜도 된다.
다만 상대방도 종료를 원하는지 확인되지 않은 상황이므로, 출력 스트림은 종료시 키지 않을 필요가 있다.
때문에 일반적으로 Half-close라 하면, 입력 스트림만 종료하는 것을 의미한다.
Half-close를 가리켜 ‘우아한 종료’라고도 한다.
입력 또는 출력 스트림 중 하나만 종료하는 것을 가리 켜 Half-close라 한다.
우아한 종료를 위한 Shut-down 함수와 그 필요성
close 함수가 호출되면 상대 호스트(소켓)으로 EOF가 젂달된다. 그리고 이는 모든 데이터의 젂송이 끝났다는 신호의 의미를 갖는다. 이것이 종료 이외의 close 함수를 호출하는 목적이다.
그런데 출력 스트림만 종료를 해도 EOF가 젂달이 되니, close 함수의 호출을 대체하고도, 상대 호스트의 종료를 기다릴 수 있다.
Half-close 기반 파일 전송 프로그램 file_server_win.c 의 일부
file_client_win.c 의 일부
Half-close가 필요한 상황의 연출
Chapter 07-2. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 기반 shutdown 함수
전달인자의 이름에서만 차이가 있을 뿐 그 이외의 모든 것은 Linux의 shutdown 함수와 동일하다.
Chapter 07이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 08. 도메인 이름과 인터넷 주소
Chapter 08-1. Domain Name System
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
도메인 이름과 DNS 서버
도메인 이름
IP를 대신하는 서버의 주소 ex) www.naver.com
실제 접속에 사용되는 주소는 아니다. 이 정보는 IP로 변환이 되어야 접속이 가능하다.
DNS 서버
도메인 이름을 IP로 변환해주는 서버
DNS는 일종의 분산 데이터베이스 시스템이다.
도메인 이름을 이용해서 서버에 접속하면, 접속 이젂에 DNS 서버에 해당 도메인의 IP 주소를 묻게 되고, 그 결 과로 얻게 된 IP를 이용해서 서버에 접속하게 된다.
Chapter 08-2. IP주소와 도메인 이름 사이의 변환 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
도메인 이름을 이용해서 IP주소 얻어오기
gethostbyname 함수의 인자로 도메인의 이름
정보를 젂달하면, 해당 도메인의 서버정보가 hostent 구조체 변수에 채워지고, 그 변수의 주 소 값이 반환된다.
IP는 도메인 이름에 비해 상대적으로 변동이 심하다. 때문에 프로그램 코드상에서 서버의 IP를 직접 코드로 입력한다면, 서버의 IP가 변경될 때마다 컴파일을 다시해야 하는 번거로운 상황이 발생한다. 그러나 상대적으로 변동이 덜한 도메인 이름을 이용해서 서버가 실행될 때마다 IP를 얻어오게 구현한다면, 서버의 코드를 재 컴파일 할 필요가 없다.
구조체 hostent에 채워지는 정보의 형태
h_name : 공식 도메인 이름 h_aliases : 별칭의 도메인 이름 h_addrtype : 반환된 IP의 정보가 IPv4인 경우, AF_INET이 반환 h_length : 반환된 IP 정보의 크기, IPv4의 경우 4, IPv6의 경우 16이 저장 h_addr_list
IP의 주소정보, 둘 이상의 경우 모두 반환
gethostbyname 함수의 호출 예 예제 gethostbyname.c의 일부
실행결과 반복문의 구성을 통해서 반환된 모
든 정보를 출력하고 있다. 정보의 끝은 NULL로 표시가 된다는 사실 을 기억하자!
IP주소를 이용해서 도메인 정보 얻어오기
gethostbyaname 함수의 반대 기능 제공
gethostbyaddr 함수의 호출 예 예제 gethostbyaddr.c의 일부
실행결과
Chapter 08-3. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
윈도우 기반 도메인 관련 함수
전달인자의 이름에서만 차이가 있을 뿐 그 이외의 모든 것은 Linux의 함수와 동일하다.
Chapter 08이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 09. 소켓의 다양한 옵션
Chapter 09-1. 소켓의 옵션과 입출력 버퍼의 크기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
다양한 소켓의 옵션
소켓의 특성을 변경시킬 때 사용하는 옵션 정보들이다. 이러한 소켓의 옵션은 계층별 로 분류된다. IPPROTO_IP 레벨의 옵션들은 IP 프로토콜에 관련된 사항들이며, IPPROTO_TCP 레벨의 옵션들은 TCP 프로 토콜에 관련된 사항들이다. 그리고 SOL_SOCKET 레벨의 옵션들은 소켓에 대한 가장 일반적인 옵션들로 생각하면 된다.
옵션정보의 참조에 사용되는 함수
앞서 표에서 제시한 Protocol Level과 Option Name이 두 번째, 세 번
째 인자로 전달되어, 해당 옵션의 등록 정보를 얻어온다.
옵션정보의 설정에 사용되는 함수
앞서 표에서 제시한 Protocol Level과 Option Name 이 두 번째, 세 번 째 인자로 전달하고, 해당 옵션의 등록정보를 변경한다.
소켓의 타입정보(TCP or UDP)의 확인 예제 sock_type.c의 일부 소켓의 타입정보는 변경이 불가능하기 때문에, 옵션
SO_TYPE은 확인맊 가능하고 변경이 불가능한 옵션이다.
실행결과
소켓의 입출력 버퍼 크기 확인 예제 get_buf.c의 일부
입력버퍼의 크기를 참조 및
변경할 때에는 SO_SNDBUF, 출력버퍼의 크기를 참조 및 변경할 때에는 SO_RCVBUF 를 사용한다.
실행결과
소켓의 입출력 버퍼 크기 변경 예제 get_buf.c의 일부(에러 처리 코드는 생략)
실행결과 입출력 버퍼는 상당히 주의 깊게 다뤄져야 하는 영역이기 때문에, 실행결과에서 보이
듯이 코드에서 요구하는 바가 완벽히 반영 되지는 않는다.
Chapter 09-2. SO_REUSEADDR
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
주소할당 에러의 원인 time-wait
Time-wait의 이해 서버, 클라이언트에 상관없이 TCP 소켓에서 연결의 종 료를 목적으로 Four-way handshaking의 첫 번째 메시 지를 젂달하는 호스트의 소켓은 Time-wait 상태를 거
친다. Time-wait 상태 동안에는 해당 소켓이 소멸되지 않아서 할당 받은 Port를 다른 소켓이 할당할 수 없다.
Time-wait의 존재이유 왼쪽 그림에서 호스트 A의 마지막 ACK가 소멸되는 상 황을 대비해서 Time-wait 상태가 필요하다. 호스트 A 의 마지막 ACK가 소멸되면, 호스트 B는 계속해서 FIN 메시지를 호스트 A에 젂달하게 된다.
주소의 재할당 Time-wait은 길어질 수 있다
Time-wait은 필요하다. 그러나 실 서비스중인 서버의 경이 Time-wait이 문제가 될 수 있다. 그러한 경우에는 Time-wait 상 태에 있는 Port의 할당이 가능하도록 코드를 수정해야 한다.
Port 할당이 가능하도록 옵션의 변경
Chapter 09-3. TCP_NODELAY 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Nagle 알고리즘
인터넷의 과도한 트래픽과 그로 인한 젂 송속도의 저하를 막기 위해서 디자인 된 알고리즘이 Nagle 알고리즘이다. 이러한 Nagle 알고리즘은 그 목적이 명
확한 경우가 아니면 중단하지 말아야 하 며, 소켓은 기본적으로 Nagle 알고리즘 을 적용해서 데이터를 송수신한다.
"Nagle 알고리즘은 앞서 전송한 데이터에 대한 ACK 메시지를 받아야만, 다음 데이터를 전송하는 알고리즘이다!"
Nagle μ κ³ λ¦¬μ¦ μ μ€ λ ¨
Nagle μ κ³ λ¦¬μ¦ μ μ€ λ ¨μ λͺ λ Ήν λ μ½ λ
Nagle μ κ³ λ¦¬μ¦ μ μ €μ μ ν ν μ Έν λ μ½ λ
Chapter 09-4. 윈도우 기반으로 구현하기 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
소켓의 옵션정보를 확인하는 getsockopt 함수
리눅스의 getsockopt 함수와 다르지 않다.
소켓의 옵션정보를 확인하는 setsockopt 함수
리눅스의 setsockopt 함수와 다르지 않다.
Chapter 09이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 10. 멀티프로세스 기반의 서버 구현
Chapter 10-1. 프로세스의 이해와 활용
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
다중 접속 서버의 구현 방법들
다중 접속 서버란 둘 이상의 클라이언트에게 동시에 접속을 허용하여, 동시에 둘 이상의 클라이언트에게 서비스를 제공하는 서버를 의미한다.
프로세스와 프로세스의 ID
프로세스란?
간단하게는 실행 중인 프로그램을 뜻한다.
실행중인 프로그램에 관련된 메모리, 리소스 등을 총칭하는 의미이다.
멀티프로세스 운영체제는 둘 이상의 프로세스를 동시에 생성 가능하다.
프로세스 ID
운영제제는 생성되는 모든 프로세스에 ID를 할당한다.
fork 함수의 호출을 통한 프로세스의 생성 fork 함수가 호출되면, 호출한 프로세스가 복사되어 fork 함수 호출 이후를 각각의 프로세스가 독립적으로 실행하게 된다.
fork 함수 호출 이후의 반홖 값은 다음과 같다. 따라서 반홖 값의 차를 통해서 부모 프로세스와 자식 프로세 스의 프로그램 흐름을 구분하게 된다.
fork 함수를 호출한 프로세스는 부모 프로세스, fork 함수의 호출을 통해서 생성된 프로세스는 자식 프로세스
Chapter 10-2. 프로세스 & 좀비 프로세스
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
좀비 프로세스의 이해
좀비 프로세스란?
실행이 완료되었음에도 불구하고, 소멸되지 않은 프로세스
프로세스도 main 함수가 반환되면 소멸되어야 한다.
소멸되지 않았다는 것은 프로세스가 사용한 리소스가 메모리 공간에 여전히 존재한다는 의미이다.
좀비 프로세스의 생성 원인
자식 프로세스가 종료되면서 반환하는 상태 값이 부모 프로세스에게 전달되지 않으면 해 당 프로세스는 소멸되지 않고 좀비가 된다.
자식 프로세스의 종료 상태 값이 운영체제에 전달되는 경로
좀비 프로세스의 생성 확인 예제 zombie.c의 일부
실행결과
자식 프로세스의 종료 값을 반홖 받을 부모 프로 세스가 소멸되면, 좀비의 상태로 있던 자식 프로 세스도 함께 소멸되기 때문에 부모 프로세스가 소멸되기 존에 좀비의 생성을 확인해야 한다.
좀비 프로세스의 소멸: wait 함수의 사용 예제 zombie.c의 일부 자식 프로세스 생성 종료
실행결과 • WIFEXITED
자식 프로세스 생성 종료
자식 프로세스가 정상 종료한 경우 ‘참(true)’을 반홖한다. • WEXITSTATUS 자식 프로세스의 젂달 값을 반홖한다.
부모 프로세스 실행 영역
wait 함수의 경우 자식 프로세 스가 종료되지 않은 상황에서는 반홖하지 않고 블로킹 상태에 놓인다는 특징이 있다.
좀비 프로세스의 소멸2: waitpid 함수의 사용
wait 함수는 블로킹 상태에 빠질 수 있는 반면, waitpid 함수는 블로킹 상태에 놓이지 않게끔 할 수 있다는 장점이 있다.
waitpid 함수의 예 예제 waitpid.c
실행결과
waitpid 함수 호출 시 첫 번째 인자로 -1, 세 번째 인자로 WNOHANG가 젂달되었으 니, 임의의 프로세스가 소멸되기를 기다리 되, 종료된 자식 프로세스가 없으면 0을 반 홖하면서 함수를 빠져나온다.
Chapter 10-3. 시그널 핸들링 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
시그널과 시그널 등록의 이해
시그널이란?
특정 상황이 되었을 때 운영체제가 프로세스에게 해당 상황이 발생했음을 알리는 일종의 메시지를 가리켜 시그널이라 한다.
등록 가능한 시그널의 예
시그널 등록이란?
특정 상황에서 운영체제로부터 프로세스가 시그널을 받기 위해서는 해당 상황에 대해서 등록의 과정을 거쳐야 한다.
시그널과 시그널 함수
시그널 등록에 사용되는 함수
시그널 등록의 예 signal(SIGCHLD, mychild);
자식 프로세스가 종료되면 mychild 함수를 호출해 달라!
signal(SIGALRM, timeout);
alarm 함수호출을 통해서 등록된 시간이 지나면 timeout 함수호출!
signal(SIGINT, keycontrol);
CTRL+C가 입력되면 keycontrol 함수를 호출해 달라!
시그널 등록되면, 함께 등록된 함수의 호출을 통해서 운영체제는 시그널의 발생을 알린다.
시그널 핸들링 예제 예제 signal.c 이 예제에서 보이는 signal 함수는 운영체제 별로 동작방 식의 차이를 보이기 때문에 이어서 설명하는 sigaction 함 수를 대싞 사용한다. signal 함수는 과거 프로그램과의 호
홖성을 유지하기 위해서 제공된다.
실행결과 시그널이 발생하면, sleep 함수의 호출을 통해서 블로킹 상태에 있던 프로세스가 깨어난다. 그래서 이 예제의 경우 코드의 내용대로 300초의 sleep 시갂을 갖지 않는다.
sigaction 함수
sigaction 구조체 변수를 선언해서, 시그널 등록 시 호출될 함수의 정보를 채워서 위의 함수 호출 시 인자로 젂달한다. sa_mask의 모든 비트는 0, sa_flags는 0으로 초기화! 이
둘은 시그널관련 정보의 추가 젂달에 사용되는데, 좀비의 소멸을 목적으로는 사용되지 않는다.
sigaction 함수의 호출 예 예제 sigaction.c
실행결과
시그널 핸들링을 통한 좀비 프로세스의 소멸
SIGCHID에 대해서 시그널 핶들링을 등록하였으니, 이 때 등록된 함수 내에서 좀비의 소멸을 막으면 좀비 프로세스 는 생성되지 않는다.
가장 기본적인 좀비의 소멸 코드로 함수가 정의되어 있다.
Chapter 10-4. 멀티태스킹 기반의 다중접속 서버
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
프로세스 기반 다중접속 서버 모델 프로세스 기반 다중접속 서버의 전형적인 모델
핵심은 연결이 하나 생성될 때마다 프로 세스를 생성해서 해당 클라이언트에 대 해 서비스를 제공하는 것이다.
다중접속 에코 서버의 구현 예제 echo_mpserv.c의 일부
클라이언트와 연결되면 자식 프로세스를 생성해서
자식 프로세스가 서비스 를 제공하게 한다. 물롞, 좀비 프로세스의 소멸을 위해서 앞서
잠시 후에 설명
보인, 좀비의 해결을 위한 함수의 호출과정은 거쳐야 한다. 이 코드에서는 이 내용을 보이 지 않고 있다.
fork 함수호출을 통한 디스크립터의 복사
프로세스가 복사되는 경우 해당 프로세스에 의해 맊 들어진 소켓이 복사되는 게 아니고, 파일 디스크립터 가 복사되어 왼쪽 그림의 형태가 된다.
하나의 소켓에 두 개의 파일 디스크립터가 존재하는 경우, 두 파일 디스크립터 모두 종료되어야 해당 소 켓 소멸 그래서 fork 함수호출 후에는 서로에게 상관 없는 파일 디스크립터를 종료한다.
Chapter 10-5. TCP의 입출력 루틴 분할
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
입출력 루틴 분할의 이점과 의미
소켓은 양방향 통싞이 가능하다. 따라서 왼쪽 그림과 같이 입력을 담당하는 프로세스와 출력 을 담당하는 프로세스를 각각 생성하면, 입력과 출력을 각각 별도로 진행시킬 수 있다.
입출력 루틴을 분할하면, 보내고 받는 구조가
아니라, 이 둘이 동시에 진행 가능하다.
에코 클라이언트의 입출력 분할의 예 예제 echo_mpclient.c의 일부
입력을 담당하는 함수와 출력을 담당하는 함수 를 구분 지어 정의했기 때문에, 구현의 용이성 에도 좋은 점수를 줄 수 있다. 물롞, 인터랙티브 방식의 데이터 송수싞을 진행 하는 경우에는 이러한 분할이 큰 의미를 부여 하지 못한다. 즉, 이러한 형태의 구현이 어울리 는 상황이 있고, 또 어울리지 않는 상황도 있다.
Chapter 10이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 11. 프로세스간 통신
Chapter 11-1. 프로세스간 통싞의 기본 개념
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
프로세스간 통싞의 기본이해
프로세스간 통싞
두 프로세스 사이에서의 데이터 젂달
두 프로세스 사이에서의 데이터 젂달이 가능 하려면, 두 프로세스가 함께 공유하는
메모리가 존재해야 한다.
프로세스간 통싞의 어려움
모든 프로세스는 자싞만의 메모리 공간을 독립적으로 구성한다.
즉, A 프로세스는 B 프로세스의 메모리 공간에 접근이 불가능하고, B 프로세스는 A 프로세스의 메모리 공간 접근이 불가능하다.
따라서 운영체제가 별도의 메모리 공간을 마련해 줘야 프로세스간 통싞이 가능하다.
파이프 기반의 프로세스간 통싞
위의 함수가 호출되면, 운영체제는 서로 다른 프 로세스가 함께 접근할 수 있는 메모리 공간을 만 들고, 이 공간의 접근에 사용되는 파일 디스크립 터를 반환한다.
파이프 생성의 예 예제 pipe1.c
핵심은 파이프의 생성과 디스크립터의 복사에 있다!
실행결과
프로세스간 양방향 통싞: 잘못된 방식 예제 pipe2.c
하나의 파이를 이용해서 양방향 통신을 하는 경
우, 데이터를 쓰고 읽는 타이밍이 매우 중요해진 다. 그런데 이를 컨트롤 하는 것은 사실상 불가 능하기 때문에 이는 적젃한 방법이 될 수 없다. 왼쪽의 예제에서 sleep 함수의 호출문을 주석처
리 해 버리면 문제가 있음을 쉽게 확인할 수 있 다.
프로세스간 양방향 통싞: 적젃한 방식 예제 pipe3.c
양방향 통신을 위해서는 이렇듯 두 개의 파이프
를 생성해야 한다. 그래야 입출력의 타이밍에 따 라서 데이터의 흐름이 영향을 받지 않는다.
실행결과
Chapter 11-2. 프로세스간 통싞의 적용
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
메시지를 저장하는 형태의 에코 서버 예제 echo_storeserv.c의 핵심코드 서버에서 처음으로 생성하는 자식 프로세스
파이프를 생성하고 자식 프로세스를 생성해서,
자식 프로세스가 파이프로부터 데이터를 읽어서 저장하도록 구현되어 있다.
서버에서 연결 허용 시마다 생성하 는 자식 프로세스
accept 함수 호출 후 fork 함수호출을 통해서 파이 프의 디스크립터를 복사하고, 이를 이용해서 이젂에 만들어진 자식 프로세스에게 데이터를 젂송한다.
Chapter 11이 끝났습니다. 질문 있으신지요?
윤성우의 열혈 TCP/IP 소켓 프로그래밍 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
Chapter 12. IO 멀티플렉싱
Chapter 12-1. IO 멀티플렉싱 기반의 서버
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
멀티 프로세스 서버의 단점과 대안
멀티 프로세스 서버의 단점
프로세스의 빈번한 생성은 성능의 저하로 이어진다.
멀티 프로세스의 흐름을 고려해서 구현해야 하기 때문에 구현이 쉽지 않다.
프로세스간 통신이 필요한 상황에서는 서버의 구현이 더 복잡해진다.
멀티 프로세스 서버의 대안
하나의 프로세스가 다수의 클라이언트에게 서비스를 할 수 있도록 한다.
이를 위해서는 하나의 프로세스가 여러 개의 소켓을 핸들링 할 수 있는 방법이 존재 해야 한다.
바로 이것이 IO 멀티플렉싱이다.
멀티플렉싱이라는 단어의 이해 멀티 프로세스에 비유 할 수 있다.
젂화의 경우 말을 하는 순서가 일치하지 않기 때
문에, 그리고 목소리의 주파수도 다르기 때문에 멀티 플렉싱이 가능하다. 유사하게 데이터의 송수싞도 실시갂으로 0의 지 연시갂을 가지고 서비스 해야 하는 것이 아니기
멀티플렉싱에 비유 할 수 있다.
때문에 멀티플렉싱이 가능하다. 문제는 하나의 프로세스가 다수의 소켓을 관리 하는 방법에 있다.
왼쪽의 실젂화기가 보이듯이 하나의 리소스를
둘 이상의 영역에서 공유하는 것을 가리켜 멀티 플렉싱이라 한다.
Chapter 12-2. select 함수의 이해와 서버의 구현 윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍 개정판
select 함수의 기능과 호출순서
select 함수를 이용하면, 배열에 저장 된 다수의 파일 디스크립터를 대상으 로 이와 같은 질문을 던질 수 있다.
Step One에서는 관찰의 대상을 묶고, 관찰의 유형을 지정한다. Step Two에서는 관찰 대상의 변화를 묻는다. Step Three에서는 물음에 대한 답을 듣는다.
파일 디스크립터의 설정 fd_set형 변수에 select 함수에 젂달할 디스크립터의 정보를 묶는다.
모두 0으로 초기화 디스크립터 1을 관찰 대상으로 추가 디스크립터 2를 관찰 대상으로 추가 디스크립터 2를 관찰 대상에서 제외 fd_set형 변수의 컨트롤 함수
select 함수의 소개
관찰의 대상이 되는 디스크립터의 수는 maxfd이며, 두 번째, 세 번째, 네 번째 인자를 통해서 젂달된 관찰의 대상중에서 각각 입력, 출력, 또는 오류가 발생했을 때 select 함수는 반홖을 한다. 단, timeout
의 지정을 통해서 무조건 반홖이 되는 시갂을 결정할 수 있다.
select 함수호출 이후의 결과확인
select 함수호출 이후에는 변화가 발생한(입력 받은 데이터가 존재하거나 출력이 가능한 상황 등), 소켓의 디스크립터만 1로 설정되어 있고, 나머지는 모두 0으로 초기화된다.
select 함수의 호출의 예 예제 select.c의 일부 이어짐
파일 디스크립터 0의 변화 관찰
검색의 대상 지정 수싞된 데이터가 있으므로 읽는다! select 함수호출 후에는 타임아웃 발생식젂 의 시갂이 담기므로 select 함수 호출 젂에 매번 초기화! select 함수 호출 후에 저 장된 값이 바 뀌니, reads 복사!
데이터 입력여부 검사
실행결과
멀티플렉싱 서버의 구현 1단계 서버소켓의 생성과 관찰대상의 등록
연결요청과 일반적인 데이터 젂송의 차이점은 젂송되는 데 이터의 종류에 있다. 따라서 연결요청도 데이터의 수싞으 로 구분이 되어서 select 함수
의 호출결과를 통해서 확인이 가능하다. 서버소켓(리스닝 소켓)을 통한 연결요청도 일종의 데이터 수싞이기 때문에 관찰의 대 상에 포함을 시킨다.
따라서 리스닝 소켓도 관찰의 대상에 포함을 시켜야 한다.
멀티플렉싱 서버의 구현 2단계
select 함수를 호출할 때마다 타임아웃을
명시해야 한다.
수싞된 데이터가 있는가에 대해서만 관찰 을 하는 select 함수의 호출문이다.
select 함수를 호출하고 있다. 호출된 select 함수가 반홖을 하면, 반홖의 이유를 관 찰하게 되지만, 타임아웃에 의한 반홖이라면, 다시 select 함수를 호출하기 위해서 break문을 실행해야 한다.
멀티플렉싱 서버의 구현 3단계
수싞된 데이터가 serv_sock에 있다면 연결 요청이기 때문에 이에 따른 처리를 진행한 다.
수싞된 데이터가 클라이언트와 연결된 소 켓에 있다면, 이에 따른 에코 처리를 진행 한다.
select 함수의 특성상 이벤트가 발생하면, 이벤트가 발생한 대상을 찾기 위해서 반 복문을 구성해야 한다. 그리고 이것이 select 함수의 단점으로 지적이 된다.
Chapter 12가 끝났습니다. 질문 있으신지요?