Tuesday, July 13, 2010

chapter 3 (주소체계와 데이터 정렬)

IP : internet protocol, 데이터의 송수신을 위해 컴퓨터에 부여하는 값
PORT 번호 : 프로그램에서 생성되는 소켓을 구분하기 위해 소켓에 부여되는 번호

-소켓에 할당되는 IP주소와 PORT번호-


인터넷 주소(Internet Address, IP 주소) : IPv4 (4바이트 주소 체계), IPv6 (6 바이트 주소체계), IPv6는 IP가 부족할것을 고려해 만든 체계이나 아직 IPv4가 대세. IPv4는 그림과 같이 A~E 클래스로 분류된다. E 클래스는 일반적이지 않고 예약되어 있다. 그림에서 나오는 네트워크 주소 (network ID) 란 네트워크 구분의 위한 IP주소의 일부. 예를 들어 데이터를 203.211.172.103의 컴퓨터로 전송한다고 할때 우선은 IP주소의 네트워크 ID (여기서는 203.211.172)로 데이터를 보내고 라우터(네트워크 안의 호스트와 외부의 데이터 송수신을 위한 물리적 장치)가 나머지 호스트 ID (여기서는 172)로 데이터를 전송한다.


IP 주소의 클래스 구분법 : 
클래스 A 의 첫 바이트 범위 0 ~ 127
클래스 B 의 첫 바이트 범위 128 ~ 191
클래스 C 의 첫 바이트 범위 192 ~ 223


소켓의 구분에 활용되는 PORT번호 : IP는 컴퓨터를 구분하기 위한 값이다. 이런 IP를 보고 전달된 데이터는 컴퓨터의 수많은 프로그램 중에 어떤 프로그램에 사용되어야 하는지 구분되어지기 위해 사용되는 것이 PORT번호이다. 이 PORT번호를 통해 운영체제가 해당 소켓에 데이터를 분배한다. 즉 하나의 운영체제 내에서 소켓을 구분하기 위한것이 PORT 번호이다. 16 비트 (0~65535)이다. 중복되어선 안되며 0~1023는 well-known PORT라고 해서 특정 프로그램에 할당되어져 있기에 이를 제외해서 사용한다.



-주소정보의 표현-


IPv4 기반의 주소표현을 위한 구조체 : 주소정보에는 프로토콜 체계 (예: IPv4), IP 주소, PORT 번호가 들어가 있어야 한다.
오른쪽 구조체에 사용된 자료형과 멤버는 책을 참조. 매우 중요




-네트워크 바이트 순서와 인터넷 주소 변환-


이부분의 위의 주소정보표현의 구조체인 sockaddr_in의 멤버 sin_port와 sin_zero를 위한 것이다.
CPU마다 메모리에 데이터를 저장하고 해석하는 방식이 다르다(호스트 바이트 순서).
빅 엔디안 (Big Endian) : 상위 바이트의 값을 작은 번지수에 저장하는 방식
리틀 엔디안 (Little Endian) : 상위 바이트의 값을 큰 번지수에 저장하는 방식, 대표적으로 intel 계열의 CPU
그래서 CPU마다 다른 방식으로 데이터 저장 방식(호트스 바이트 순서)이 다르므로 이를 통일하고 한것이 "네트워크 바이트 순서"로 빅 엔디안을 뜻한다.
바이트 순서를 변환해주는 함수:
unsigned short htons(unsigned short);
unsigned short ntons(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntonl(unsigned long);
htons 에서 h는 host를 s는 short를 의미, 즉 htons(h to n s)는 PORT번호(short형 데이터) 를 호스트 바이트 순서에서 네트워크 바이트 순서로 변환하라는 의미



-인터넷 주소의 초기화와 할당-


다음은 코드 설명이 많으므로 책 참조
문자열 정보를 네트워크 바이트 순서의 정수로 변환하기 : 우리가 익숙한 IP 주소는 점이 찍힌 십진수 표현 방식 (Dotted-Decimal Notation)으로 이를 32비트 정수형으로변환해주는 함수가 필요한데 이것이 inet_addr와 inet_aton이다. 차이점은 inet_addr는 성공시 in_addr_t (unsigned 32 bit int)를 실패시 INADDR_NONE을 반환하는 반면,  inet_aton은 성공시 1을 실패시 0을 반환하고 매개변수로 구조체인 in_addr의 주소를 받아서 성공시 그곳에 변환된 값을 넣는다.
inet_aton과 반대 역활, 그러니까 32비트 정수형으로 되어 있는 IP를 Dotted-Decimal Notation으로 변환해 주는 함수가 inet_ntoa이다.


인터넷 주소의 초기화 : 아래 그림 참조


클라이언트의 주소정보 초기화 : 클라이언트의 connet 함수 역시 구조체 sockaddr_in를 사용하나 IP와 PORT의 대상이 다르다. 서버 bind 함수의 경우 서버의 IP와 PORT를, 클라이언트의 connect 함수의 경우 서버의 IP와 PORT를 넣어야 한다.
서버의 경우 "IP 211.217.168.13 PORT 9190으로 들어오는 데이터는 내게 보내라"
클라이언트의 경우 "IP 211.217.168.13 PORT 9190으로 연결해라" 라는 의미


INADDR_ANY : 위에서 처럼 매번 bind 함수에 IP를 넣는 것이 귀찮기 때문에 자동화로 IP를 받을 수 있다. 위에 그림에서 serv_ip를 선언하지 말고 addr.sin_addr.s_addr=inet_addr(serv_ip); 대신 
addr.sin_addr.s_addr=htonl(INADDR_ANY); 라고 하면 자동으로 IP가 할당된다.


서버소켓 초기화 과정 : 소켓선언과 함께 위 내용을 최종 정리하면 다음 그림과 같다(1장에서 3장까지의 내용 총괄).

chapter 2 (소켓의 타입과 프로토콜의 설정)

-소켓의 프로토콜과 그에 따른 데이터 전송 특성-


프로토콜(protocol)이란?
컴퓨터 상호간의 대화에 필요한 통신 규약... 너무 식상한 답변이다. 와닿지 않는다.

소켓(socket) 함수?
인자로 domain (소켓이 사용할 프로토콜 체계 정보 전달), type (소켓의 데이터 전송 방식에 대한 정보 전달), protocol (두 컴퓨터 간 통신에 사용되는 프로토콜 정보 전달) 을 받고 호출 성공시 파일 디스크립터, 실패시 -1 return.

프로토콜 체계(protocol family)? PF_INET, PF_INET6, PF_LOCAL, PF_PACKET, PF_IPX (자세한건 책 참조)

소켓의 타입(type)? 소켓의 데이터 전달 방식. 프로토콜 체계가 정해졌다고 해도 그 안에서 둘 이상의 전송 방식이 있으므로 선택해야 한다. 대표적으로 연결지향형 소켓과 비 연결지향형 소켓.
1. 연결지향형 소켓(SOCK_STREAM) : 독립된 별도의 라인을 통해서 데이터를 전달하는 방식으로 라인상 문제가 없다면; 중간에 데이터 소멸이 없다. 전송 순서대로 데이터가 수신된다. 전송 데이터의 경계가 없다. 소켓 대 소켓의 연결은 반드시 1 대 1이어야 한다.
2. 비 연결지향형 소켓(SOCK_DGRAM) : 전송 순서에 상관없이 가장 빠른 전송을 지향한다. 전송되는 데이터의 손실 및 파손의 우려가 있다. 데이터의 경계가 존재한다. 한번에 전송하는 데이터의 크기가 제한된다.
*데이터 경계가 있다 없다는 데이터 전송을 두번했으면 수신도 두번해야 할경우 경계가 있는것이고 전송 횟수에 상관없이 수신횟수가 있는것을 경계가 없다고 한다.

프로토콜의 최종 선택? 소켓 함수의 세번째 인자.이미 첫번째와 두번째 인자로 충분하기에 세번째 인자가 0이어도 상관이 없으니 특별한 경우 세번째 인자가 필요하다.
"하나의 프로토콜 체계 안에 데이터의 전송 방식이 동일한 프로토콜이 둘 이상 존재할 경우" 전송 방식이 동일한 프로토콜일 경우 이를 좀 더 구체화 해야 한다.

TCP 소켓 :  프로토콜 체계는 IPv4인 PF_INET 이고 데이터 전송 방식은 연결지향형인 SOCK_STREAM 인 유일한 소켓.
UDP 소켓 : PF_INET 이고 SOCK_DGRAM 인 유일한 소켓.

chapter 1 (네트워크 프로그래밍과 소켓의 이해)

소켓 프로그래밍은 다른말로 하면 네트워크 프로그래밍이다. 인터넷이라는 거대한 네트워크 망에 데이터를 주고 받기 위해서는 소켓이라는 꼭다리가 필요하다. 


연결요청을 수락하는 기능의 프로그램을 가르켜 '서버' 라고 하며 기본적으로 다음과 같은 소켓의 생성 과정을 갖는다.
1.소켓 생성 (socket)
2.IP 주소와 PORT번호 할당 (bind)
3.연결요청 가능상태로 변경(listen)
4.연결요청에 대한 수락(accept)


연결요청을 진행하는 프로그램을 가르켜 '클라이언트'라고 이 클라이언트 소켓은 connect 함수로 생성한다.


리눅스는 소켓을 파일의 일종으로 구분한다. 반면 윈도우는 파일과 소켓을 구분하기에 별도의 데이터 송수신 함수를 참조해야 한다 (윈도우 내용은 생략한다).


리눅스에서 소켓을 파일의 일종으로 취급하기에 저수준 파일 입출력 함수(저수준이란 ANSI 표준에서 정의한 함수가 아닌 운영체제가 독립적으로 제공하는 함수)인 open, close, write, read 함수로 처리가 된다.


-파일 디스크립터 : 스트림에 할당한 번호로 운영체제에서 스트림을 편하게 구분하기 위해 붙인 숫자. 윈도우에서는 '파일 핸들'이라고도 한다.