SlideShare ist ein Scribd-Unternehmen logo
1 von 15
Downloaden Sie, um offline zu lesen
TCP/IP 소켓 프로그래밍 기초 - windows 위주로 
네트워크 프로그래밍과 소켓의 이해 1. 간단한 이해 네트워크 프로그래밍이란 네트워크로 연결되어 있는 서로 다른 두 컴퓨터가 데이터를 주 고 받을 수 있도록 하는 것이다. 오늘날 대부분의 컴퓨터는 인터넷이라는 거대한 네트워크로 연결 되어 있다. 이러한 물 리적 연결된 네트워크상에서의 데이터 송수신에 사용할 수 있는 소프트웨어적인 장치를 ‘소켓’ 이라고 한다. 즉, 프로그래밍에서의 ‘소켓’은 네트워크 망의 연결에 사용되는 도구이다. 
2. 전화 받는 소켓의 구현 소켓 중 TCP소켓이 전화기에 비유가능, 전화는 거는 것과 받는 것이 모두 가능하지만 소 켓은 <거는 용도>의 소켓과 <받는 용도>의 소켓이 따로 존재한다. i) 소켓 생성 함수  전화 받는 소켓을 생성, 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 반환  이제 전화번호를 받아야 한다. ii) 전화번호에 해당되는 ip와 포트번호라는 소켓의 주소정보를 할당 소켓에 주소 정보를 할당, 성공 시 0, 실패 시 SOCKET_WRROR 반환  이제 전화 케이블에 연결해 수신이 가능하게 해야 한다. iii) 소켓에 연결요청이 가능한 상태로 전환 소켓을 연결요청을 받을 수 있는 상태로 전 환, 성공 시 0, 실패 시 SOCKET_ERROR 반환  이제 전화 요청이 왔을 때 요청을 수락할 수 있게 해줘야 한다. iv) 연결 요청이 들어오면 수락하는 함수  소켓에 연결 요청이 들어오면 수락, 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 반환 
지금까지의 내용을 요약 하자면 네트워크 프로그래밍 에서 연결요청을 허락하는 소켓 생 성과정을 다음 과 같이 정리할 수 있다.
1. 소켓 생성 – socket 함수호출 
2. IP주소와 PORT번호 할당 - bind 함수호출 
3. 연결요청 가능상태로 변경 – listen 함수호출 
4. 연결요청에 대한 수락 – accept 함수호출 
이러한 연결요청을 수락하는 기능을 가진 프로그램을 ‘서버(server)’ 라고 한다. 이 과정에서 생성한 소켓을 가리켜 ‘서버 소켓’ 또는 ‘리스닝 소켓’ 이라 한다. 
3. 전화 거는 소켓의 구현 전화를 거는 소켓은 연결요청을 진행하는 ‘클라이언트 소켓’ 이다. i) 클라이언트 프로그램에서는 socket 함수호출을 통한 소켓의 생성과 connect 함수호출을 통한 서버로의 연결요청 과정만이 존재한다.  클라이언트 프로그램에서 소켓을 기반으로 연결요청을 하는 함수, 성공 시 0, 실패 시 SOCKET_ERROR를 반환 
4. Windows 에서의 소켓프로그래밍 특징 i) 헤더파일 winSock2.h를 포함, ws2_32.lib 라이브러리를 링크시켜야 한다. ii) 윈속(winsock)의 초기화 윈속 프로그래밍을 할 때에는 반드시 WSAStartup 함수호출로, 프로그램에서 요구하는 윈도우 소켓의 버전을 알리고 해당되는 라이브러리의 초기화 작업을 진행해야 한다. 
1) wVersionRequested  프로그래머가 사용할 윈속의 버전정보 전달 이 첫 번째 인자에는 상위 8비트에는 주 버전을 하위 8비트에는 부 버전 정보를 전달한다. Ex) 사용할 버전이 1.2라면 MAKEWORD(1, 2)를 입력  0x0201 반환 2) lpWSAData  WSADATA라는 구조체 변수의 주소 값 전달 iii) 초기화된 라이브러리의 해제 방법  할당된 윈속 라이브러리가 윈도우 운영체제에 반환 되면서, 윈속관련 함수의 호출이 불가능하게 만든다. iv) Windows에서의 파일 핸들과 소켓 핸들 리눅스와는 달리 윈도우에서는 파일 핸들과 소켓 핸들을 구분한다. 윈도우 에서는 정수로 표현되는 소켓의 핸들 값 저장을 위해서 typedef 선언으로 정의된 새로운 자료 형인
SOCKET이라는 변수를 사용한다. 이러한 차이가 나는 이유는 기본적으로 두 운영체제의 커널은 구조적으로 차이가 있고, 각각 구현 스타일도 다르기 때문이다. 
5. Windows 기반 입출력 함수 리눅스에서는 소켓도 파일로 간수하기 때문에, read와 write를 이용해서 데이터를 송수신할 수 있다. 그러나 윈도우는 구분이 되어있기 때문에 소켓 기반의 입출력 함수가 존재한다. i)  성공 시 전송된 바이트 수, 실패 시 SOCKET_ERROR 반환, 리눅스의 write함수와 마지막 인자를 제외하면 비슷함, 마지막 인자에는 옵션이 없다는 것을 의미하여 0을 보통 사 용 ii)  성공 시 수신한 바이트 수(EOF  0), 실패 시 SOCKET_ERROR 반환 
소켓의 타입과 프로토콜의 설정 
1. 프로토콜 이란? 멀리 떨어져있는 두 사람이 대화를 주고받기 위해서는 나름의 대화방법이 필요하다. 예를 들어 한 사람이 전화를 할 때 한 사람이 편지를 쓸 수는 없는 일이다. 이 때의 두 사람의 대화에 사용한 프로토콜은 전화라고 할 수 있다. 이렇듯 프로토콜 이란 대화에 필요한 ‘통신규약’을 의미한다.  “컴퓨터 상호간의 대화에 필요한 통신규약” 
2. 소켓의 생성 af  소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달 type  소켓의 데이터 전송방식에 대한 정보 전달 protocol  두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달 앞에서 언급하지 않았던 각각의 매개변수에 대한 자세한 설명이다. 
3. 프로토콜 체계(Protocol Family) 소켓이 통신에 사용하는 프로토콜도 부류가 나뉜다. 그리고 socket 함수의 첫 번 째 인자로, 생성되는 소켓이 사용할 프로토콜의 부류정보를 전달한다. 이러한 부류정보를 가리켜 ‘프로토콜 체계’라 한다.
이름 
프로토콜 체계 PF_INET IPv4 인터넷 프로토콜 체계 
PF_INET6 
IPv6 인터넷 프로토콜 체계 PF_LOCAL 로컬 통신을 위한 UNIX 프로토콜 체계 
PF_PACKET 
Low Level 소켓을 위한 프로토콜 체계 PF_IPX IPX 노벨 프로토콜 체계 
가장 보편화된 프로토콜 체계는 PF_INET이다. 실제 소켓이 사용할 최종 프로토콜 정보는 첫 번째 인자를 통해 지정한 프로토콜 체계 안에 존재하는 것 중 하나를 세 번째 인자에 넣어 결정한다. 
4. 소켓의 타입 소켓의 타입이란 소켓의 데이터 전송방식을 의미하는데, 이 정보를 socket 함수의 두 번째 인자로 전달한다. 첫 번째 인자로 프로토콜 체계 정보를 입력하긴 하 지만 한 프로토콜 체계에서도 둘 이상의 데이터 전송방식이 존재하기 때문에 따 로 인자를 넣어줘야 한다. 다음은, 가장 대표적인 데이터 전송방식 2가지를 소개하겠다. i) 연결지향형 소켓(SOCK_STREAM) : 독립된 하나의 라인을 통해 데이터를 주고받음  소켓 대 소켓의 연결은 반드시 1대 1 1) 독립된 별도의 전송라인을 통하기 때문에 라인에 문제만 없다면 데이터가 소 멸되지 않음을 보장받을 수 있다.  중간에 데이터가 소멸되지 않고 목적지로 전송된다. 2) 데이터는 전송라인에 올려진 순서대로 데이터가 전달된다.  전송 순서대로 데이터가 수신된다. 3) 데이터의 경계가 존재하지 않음은 다음의 상황을 표현한 것이다.  전송되는 데이터의 경계(Boundary)가 존재하지 않는다. “데이터를 전송하는 컴퓨터가 세 번의 send 함수호출을 통해서 총 100바이트를 전송 하였다. 그런데 데이터를 수신하는 컴퓨터는 한 번의 recv 함수호출을 통해서 100바이트 전부를 수신하였다.” 데이터를 송수신하는 소켓은 내부적으로 buffer배열을 가지고 있다. 그리고 소켓을 통해 전송되는 데이터는 일단 이 배열에 저장된다. 배열의 용량을 초과 하지
않는 한, 데이터가 채워진 후 한번의 recv 함수호출로 받아올 수도 있고, 반대로 여러 번의 recv 함수 호출로 받아올 수도 있다. 즉, send 함수와 recv 함수 호출 횟수는 연결지향형 소켓에서는 큰 의미를 갖지 못한다. 그래서 연결지향형 소켓은 데이터의 경계가 존재하지 않는다고 말하는 것이다. +버퍼가 꽉 채워지면? 연결지향형 소켓은 자신과 연결된 상대 소켓의 상태를 파악하면서 데이터를 전송 하기 때문에 꽉 차있다면 데이터를 수신 하지 않는다. 그리하여 데이터가 소멸되는 일은 발생하지 않는다. i ) 비 연결지향형 소켓(SOCK_DGRAM) : 오토바이 택배 서비스에 비유  연결이라는 개념 존재x 1) 출발순서에 상관없이 최대한 빨리 목적지를 향함  전송된 순서에 상관없이 가장 빠른 전송을 지향한다. 2) 택배는 그 특성상 손실 및 파손의 우려가 있다.  전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있다. 3) 오토바이에 실어서 보낼 수 있는 물건의 크기도 제한된다.  한번에 전송할 수 있는 데이터의 크기가 제한된다. 4) 택배 물건이 2개가 오면 2번에 걸쳐 수령해야 한다.  전송되는 데이터의 경계(boundary)가 존재한다. 정리하자면, “신뢰성과 순차적 데이터 전송을 보장하지 않는, 고속의 데이터 전송을 목적으로 하는 소켓” 
5. 프로토콜의 최종선택(세 번째 인자) 사실 앞에서 설명했던 ‘프로토콜 체계’와 ‘데이터 전송방식’에 대한 정보만 주어지고 세 번째 인자는 0으로 주어져도 소켓을 생성할 수 있다. 그렇다면 왜 세 번째 인자가 필요한가 하면 다음과 같은 상황 때문이다. “하나의 프로토콜 체계 안에 데이터의 전송방식이 동일한 프로토콜이 둘 이상 존 재하는 경우” 이런 경우 세 번째 인자를 통해서 원하는 프로토콜의 정보를 조금 더 구체화 하
는 것이다. 
주소체계와 데이터 정렬 
1. 인터넷 주소 인터넷에 연결하려면 IP주소를 부여 받아야 한다. 이러한 IP주소 체계는 다음과 같이 두 종류로 나뉜다. -IPv4(Internet Protocol version 4)  4바이트 주소체계 -IPv6(Internet Protocol version 6)  16바이트 주소체계 이 2가지 주소체계의 차이는 표현에 사용되는 바이트 크기에 있다. IPv6는 현재에도 거의 안 쓰이므로 생략. IPv4 기준의 4바이트 IP주소는 네트워크 주소와 호스트 주소로 나뉘며 주소의 형 태에 따라 클래스가 나뉜다. 네트워크 주소 – 네트워크 구분을 위한 IP주소의 일부 네트워크 주소를 입력하여 해당 네트워크로 데이터가 전송된 후에 라우터가 호스트 주소를 기반으로 해당되는 호스트에 데이터를 보내는 방식이다. 
2. 클래스 별 네트워크 주소와 호스트 주소의 경계 IP주소의 첫 번째 바이트만 보면 네트워크 주소가 몇 바이트인지 판단이 가능하다. 왜냐하면 클래스 별 IP주소의 경계를 나눠놓았기 때문이다. (위의 표 참조) 혹은 이렇게 표현되기도 한다. - 클래스 A의 첫 번째 비트는 항상 0으로 시작 - 클래스 B “ 10으로 시작 - 클래스 C “ 110으로 시작 이렇게 기준이 있기 때문에 네트워크로 데이터가 이동할 때 신경 쓰지 않아도 된 다. 
3. 소켓의 구분에 활용되는 PORT번호 IP는 컴퓨터를 구분하기 위한 목적으로 존재해서 IP를 가지고 목적지 컴퓨터만 알 수 있지 최종 목적지인 응용프로그램까지는 알 수가 없다. 최종 목적지를 알
려면 해당 소켓을 알아야 한다. 그렇다면 어떻게 소켓을 구분할까 우리의 컴퓨터에는 NIC(Network Interface Card)라 불리는 데이터 송수신장치가 하나씩 달려있다. IP는 데이터를 NIC를 통해 컴퓨터 내부로 전송한다. 그 후에 NIC에 수신된 데이터 안에 있는 PORT번호를 이용해서 운영체제가 해당 PORT번 호의 소켓에 데이터를 전달하는 것이다. 
4. PORT번호의 특징 i) PORT번호는 소켓을 구분하는 목적으로 사용되므로 동일한 PORT번호는 1개만 존재할 수 있다. ii) 16비트로 표현되기 때문에 할당 가능한 범위는 0~65535 이다. iii) 0~1023까지는 ‘잘 알려진 PORT(Well-known PORT)’라 해서, 특정 프로그램에 할당하기로 예약되어 있기 때문에 이 영역은 할당에서 제외해야 한다. iv) TCP소켓과 UDP소켓은 PORT번호를 공유하지 않기 때문에 중복 가능하다. 
5. IPv4 기반의 주소표현을 위한 구조체 i) sin_family 주소체계 정보를 저장한다. 
주소체계 
의미 AF_INET IPv4 인터넷 프로토콜에 적용하는 주소체계 
AF_INET6 
IPv6 인터넷 프로토콜에 적용하는 주소체계 AF_LOCAL 로컬 통신을 위한 유닉스 프로토콜의 주소체계 
ii) sin_port 16비트 PORT번호를 저장한다. 단, ‘네트워크 바이트 순서’로 저장해야 한다.
iii) sin_addr 32비트 IP주소정보를 저장한다. 이 역시 ‘네트워크 바이트 순서’로 저장해야 한다. iv) sin_zero 특별한 의미를 지니지 않는 멤버이다. 단순히 구조체 sockaddr_in 과 구조체 sockaddr의 크기를 일치시키기 위해 삽입된 멤버이다. 
6. 바이트 순서와 네트워크 바이트 순서 CPU에 따라서 4바이트 메모리 공간에 저장하는 방식이 다를 수가 있다. 때문에 이러한 부분을 고려하지 않고서 데이터를 송수신하면 문제가 발생할 수 있다.  이것은 곧 데이터의 해석순서가 다름을 뜻하기 때문이다. CPU가 데이터를 메모리에 저장하는 방식은 다음과 같이 두 가지로 나뉜다.  데이터를 해석하는 방식도 두 가지로 나뉜다는 것을 의미한다. i) 빅 엔디안(Big Endian)  상위 바이트의 값을 작은 번지수에 저장하는 방식 ii) 리틀 엔디안(Little Endian)  상위 바이트의 값을 큰 번지수에 저장하는 방식 정수 0x12345678중 0x12가 최상위 바이트 0x78이 최하위 바이트이다. 따라서 빅 엔디안 방식은 0x12부터 순서대로 저장되고, 반대로 리틀 엔디안 방식은 0x78부 터 작은 번지수에 저장된다.  이렇게 CPU마다의 데이터 저장방식을 의미하는 것이 ‘호스트 바이트 순서’라 고 한다. 이 상황에서 서로 저장하는 방식이 다른 CPU끼리 데이터 송수신을 한다면 그 과 정에서 문제가 생길 것이다. 그래서, 이 문제를 해결하기 위해 통일된 기준으로 네트워크를 사용하기로 했으며 그것이 ‘네트워크 바이트 순서’라 한다. 네트워크 바이트 순서  빅 엔디안 방식으로의 통일 
7. 바이트 순서의 변환 i)바이트 변환을 돕는 함수 h는 호스트(host) 바이트 순서를 의미, n은 네트워크 바이트 순서를 의미
그리고 s는 short, l은 long을 의미한다. 일반적으로 s가 붙는 함수는 PORT번호의 변환에 사용되고, l이 붙은 함수는 IP주소의 변환에 사용된다. +그렇다면 데이터 전송하기 전에 항상 바꿔줘야 하나?  sockaddr_in 구조체 변수에 데이터를 채울 때 이외에는 바이트 순서를 신경 쓰지 않아도 된다! 
8. 문자열 정보를 네트워크 바이트 순서의 정수로 변환하기 sockaddr_in 안에서 주소정보를 저장하기 위해 선언된 멤버는 32비트 정수형으로 정의 되어 있다. 따라서 “211.214.107.99”와 같이 점이 찍힌 십진수 표현의 문자열을 32비트 정수형으로 변환해줘야 한다. 그리고 이를 위한 함수가 존재한다. 성공 시 빅 엔디안으로 변환된 32비트 정수 값, 실패 시 INADDR_NONE 반환 위의 함수와 반대되는 기능을 하는 함수도 존재한다.  정수형태의 IP정보를 참조하여 문자열 형태의 IP정보로 변환해서 문자열의 주 소 값을 반환 한다. 주의할 점은 반환형이 char형 포인터라는 것이다. 주소 값을 반환한다는 것은 이 미 문자열이 메모리 공간엔 저장되어있음을 뜻하는데, 위 함수에서는 내부적으로 메모리공간 할당을 요청하지 않으므로 함수 호출 뒤에도 문자열 정보를 오랫동안 저장하고 싶다면 메모리 공간을 할당하는 것이 좋다. 
9. 인터넷 주소의 초기화 지금까지 살펴본 내용을 기반으로 소켓생성과정에서 흔히 등장하는 인터넷 주소정보의 초기화 방법이다. memset으로 구조체 addr을 초기화 하였는데 그 이유는 sin_zero를 0으로 초기화 하기 위함이다.  위 과정은 서버 프로그램에서 주로 등장한다 .
10. 클라이언트 주소정보 초기화 클라이언트 프로그램에서는 connect함수를 통해서 자신을 전달한다. Sockaddr_in 구조체 변수를 선언해 이를 연결할 서버 소켓의 IP와 PORT번호로 초기화한 다음에 connect함수를 호출한다. 
11. INADDR_ANY 서버 소켓의 생성과정에서 매번 서버의 IP주소를 입력하는 것은 비효율적이다. 이 때 다음과 같이 주소정보를 초기화 가능하다.  소켓이 동작하는 컴퓨터의 IP주소가 자동으로 할당된다. 
TCP 기반 서버/클라이언트 1 :데이터 전송 방법에 따라서 TCP 소켓과 UDP 소켓으로 나뉘고, TCP 소켓의 경우 연결을 지향하여 ‘스트림 기반 소켓’이라고도 이야기한다. 
1. TCP/IP 프로토콜 스택 위 그림은 데이터 송수신의 과정을 네 개의 영역으로 계층화했다는 의미로 받아들일 수 있다.  ‘인터넷 기반의 효율적인 데이터 전송’이라는 문제를 계층화 하 여 해결한 것이다.
i) LINK 계층  물리적 연결에 대한 표준 : 물리적인 영역의 표준화에 대한 결과이다. 이는 가장 기본이 되는 영역으로 LAN, WAN, MAN과 같은 네트워크 표준과 관련된 프로토콜을 정의하는 영역이다. 바로 이 부분에서의 물리적인 연결을 LINK계층이 담당한다. 
ii) IP 계층  데이터 전송을 위한 경로 지정 프로토콜 : 데이터를 목적지까지 보낼 경로를 선택하는 것이 IP계층이다. 이 계층에서 사용하는 프로토콜이 IP이다. IP의 특징은 비 연결지향적이며 신뢰할 수 없다는 것이다. 경로가 일정치 않 고, 경로를 변경할 때 데이터 손실이나 오류를 해결하지 못한다. 즉, 오류에 취약하다. 
iii) TCP/UDP 계층  IP에서 제공한 경로를 바탕으로 데이터 실 제 송수신을 담당 : IP계층에서 알려준 경로정보를 바탕으로 데이터의 실제 송수신을 담당한다. 때문에 이 계층을 가리켜 ‘전송계층’ 이라 한다. 그런데 TCP가 데이터를 보낼 때 기반이 되는 프로토콜이 IP이다. IP는 오로지 하나의 데이터 패킷이 전송되는 과정에만 중심을 두고 설계되어서 여러 개의 데이터 패킷을 전송할 때 오류를 인식 할 수가 없다. TCP 프로토콜은 이러한 오류를 해결해 준다.  TCP는 확인절차를 걸쳐서 신뢰성 없는 IP에 신뢰성을 부여한 프로토콜이라 할 수 있다. 
iv) APPLICATION 계층 : 최종적으로 소켓이라는 도구가 주어졌고, 이 도구를 이용해서 무엇인가를 만들면 프로그램의 성격에 따라 클라이언트와 서버간의 데이터 송수신에 대 한 약속이 정해지는데, 이를 가리켜 APPLICATION 프로토콜 이라한다. 네트워크 프로그래밍은 대부분 APPLICATION 프로토콜이 상당부분을 차지한다.
2. TCP기반 서버에서의 기본적인 함수호출 순서  연결대기 상태로의 진입을 위한 함수 여기서는 ‘연결요청 대기상태’의 의미와 ‘연결요청 대기 큐’라는 것에 대해서 설명할 것이다. 클라이언트의 연결요청도 인터넷을 통해서 흘러 들어오는 일종의 데이터 전송이기 때문에, 이것을 받는 소켓이 하나 있어야 한다. listen함수가 호출되면, 서버 소켓이 만들어지고 두 번째 인자로 전달되는 정수의 크기에 해당되는 대기실이 만들어진다.  ‘연결요청 대기 큐’ 
3. 클라이언트의 연결요청 수락 listen 함수호출 이후에 클라이언트의 연결요청이 들어왔다면, 들어온 순서대로 수락을 한다. 연결을 한다는 것은 곧 데이터를 주고받는 것을 의미하는데 이 때 소켓이 필요하다. 하지만 서버 소켓은 요청을 받는 역할을 하고 있으므로 소켓을 하나 더 만들어야 한다. 그러기 위한 함수가 바로 accept 함수이다. 클라이언트의 서버로의 연결요청은
위 connect 함수호출을 통해 하게 되는데 이 때 1) 서버에 의해 연결요청이 접수되거나 2) 오류로 인한 중단이 되었을 때 함수가 반환된다. 이 때 주의할 점은 1)의 상황이라 해서 서버의 accept 함수호출을 의미하는 것은 아니라는 점이다. 단지 서버의 연결요청 대기 큐에 등록된 상황을 의미할 수도 있다. 
4. Iterative 서버의 구현 accept 함수가 호출된 다음에 입출력 함수를 호출하고 있다. 그리고 이어서 close 함수를 호출하는데 이는 서버 소켓이 아니라, accept 함수의 호출로 생성된 소켓을 대상으로 하는 것이다. +그럼 서버라는 것이 한 순간에 하나의 클라이언트만 연결하는 건가? 이는 후에 프로세스와 쓰레드에 대해 공부하고 나면 둘 이상의 클라이언트에 연결하는 서버를 만들 수 있게 된다.
소켓의 우아한 연결종료 
1. 일방적인 연결종료의 문제점 윈도우의 closesocket 함수호출은 완전종료를 의미한다.  이 말은 곧, 데이터 전송과 수신이 불가능하다는 것을 의미한다. 두 개의 호스트가 연결된 상황에서 한 쪽이 closesocket함수를 호출하면 두 호스 트 간의 데이터 송수신이 불가능해 진다. 이 때, 한 쪽이 데이터 전송 후에 다른 쪽이 closesocket을 해버리면 데이터가 소멸되고 마는 문제가 발생한다.  이를 위한 해결책으로, 스트림의 일부만 종료하는 ‘Half-close’방법이 제공되고 있다. 전송과 수신 둘 중 한가지를 종료하는 것으로 스트림의 반만 닫는 것이다. 
2. 소켓과 스트림 소켓을 통해 두 호스트가 연결되면, 데이터 송수신이 가능하게 된다. 이러한 상태 를 ‘스트림이 형성된 상태’라고 한다. 스트림은 한쪽 방향으로만 형성되기 때문에 양방향 통신을 위해서는 두 개의 스트림이 필요하다. 우아한 종료라는 것은 이 중 하나의 스트림만 끊는 것을 말한다. 
3. 우아한 종료를 위한 shutdown 함수 Half-close에 사용되는 함수에는 shutdown 함수가 있다. 성공 시 0, 실패 시 SOCKET_ERROR 반환 위 함수의 두 번째 매개변수에 전달되는 인자와 그 의미는 다음과 같다. - SD_RECEIVE  입력 스트림 종료 - SD_SEND  출력 스트림 종료 - SD_BOTH  입출력 스트림 종료 입력 스트림을 종료하면 이후에 입력버퍼에 전달되는 데이터는 지워지 만, 출력
스트림을 종료한 후에 출력 버퍼에 아직 전송되지 못한 데이터가 존재하면 해당 데이터는 목적지로 전송된다. 
4. Half-close의 필요성 shutdown 함수호출의 필요성을 상황 별로 보면 알기 쉽다. 
i) 급히 종료하지 않으면 되지 않나 맞는 말이다. 이런 상황에선 굳이 Half-close를 하지 않아도 된다. 하지만 다음 상황을 보자 
ii) 클라가 서버로부터 파일은 받고, 수신완료의 메시지를 주고 종료 하 려 한다. 클라 입장에서는 서버로부터 파일을 언제까지 받아야 하는지를 알 수 없 기 때문에 메시지를 주기 위해 무작정 기다려야 한다. 하지만 이렇게 무작 정 기다리다 보면 블로킹 상태에 빠질 위험이 있기 때문에 좋지 않다. 
iii) 파일의 끝은 의미하는 EOF를 보내주면 되지 않나 그러면 된다. 그렇다면 어떻게 서버는 클라에게 EOF를 보내줄 수 있는가 
iv) 출력 스트림을 종료하면 상대 호스트로 EOF가 전송된다. closesocket 함수호출을 통해서 입출력 스트림을 모두 종료해주어도 EOF는 전송되지만, 이럴 경우 클라이언트가 서버에 보낼 데이터가 남아 있더 라도 전송 할 수 없게 된다. 이럴 경우에 EOF도 전송되고 입력스트림은 여전히 살아있어서 데이터 의 수신도 가능케 하는 Half-close함수 shutdown을 호출해주어야 하는것 이다.

Weitere ähnliche Inhalte

Was ist angesagt?

[네트워크] TCP, 믿을 수 있나요!?
[네트워크] TCP, 믿을 수 있나요!?[네트워크] TCP, 믿을 수 있나요!?
[네트워크] TCP, 믿을 수 있나요!?
용민 박
 
Icmp Attak Against Tcp
Icmp Attak Against TcpIcmp Attak Against Tcp
Icmp Attak Against Tcp
xyzlee
 
네트워크의 개념
네트워크의 개념네트워크의 개념
네트워크의 개념
Chulgyu Shin
 

Was ist angesagt? (20)

[네트워크] TCP, 믿을 수 있나요!?
[네트워크] TCP, 믿을 수 있나요!?[네트워크] TCP, 믿을 수 있나요!?
[네트워크] TCP, 믿을 수 있나요!?
 
20150525 open flow1.3_ryu_sdn_link aggregation 1_김지은
20150525 open flow1.3_ryu_sdn_link aggregation 1_김지은20150525 open flow1.3_ryu_sdn_link aggregation 1_김지은
20150525 open flow1.3_ryu_sdn_link aggregation 1_김지은
 
파이썬+네트워크 20160210
파이썬+네트워크 20160210파이썬+네트워크 20160210
파이썬+네트워크 20160210
 
Ryu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic MonitorRyu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic Monitor
 
Python socket programming
Python socket programmingPython socket programming
Python socket programming
 
Wire shark 사용법 및 네트워크 개론 살짝 설명
Wire shark 사용법 및 네트워크 개론 살짝 설명Wire shark 사용법 및 네트워크 개론 살짝 설명
Wire shark 사용법 및 네트워크 개론 살짝 설명
 
네트워크 기본
네트워크 기본네트워크 기본
네트워크 기본
 
150416 OpenStack Networking with Neutron Jieun, Kim
150416 OpenStack Networking with Neutron Jieun, Kim150416 OpenStack Networking with Neutron Jieun, Kim
150416 OpenStack Networking with Neutron Jieun, Kim
 
Python Network Programming
Python Network ProgrammingPython Network Programming
Python Network Programming
 
Icmp Attak Against Tcp
Icmp Attak Against TcpIcmp Attak Against Tcp
Icmp Attak Against Tcp
 
스트리밍 프로토콜
스트리밍 프로토콜스트리밍 프로토콜
스트리밍 프로토콜
 
실무로 배우는 시스템 성능 최적화 10부. 네트워크 모니터링
실무로 배우는 시스템 성능 최적화   10부. 네트워크 모니터링실무로 배우는 시스템 성능 최적화   10부. 네트워크 모니터링
실무로 배우는 시스템 성능 최적화 10부. 네트워크 모니터링
 
Network researching
Network researchingNetwork researching
Network researching
 
네트워크의 개념
네트워크의 개념네트워크의 개념
네트워크의 개념
 
Network Project
Network ProjectNetwork Project
Network Project
 
DPDK
DPDKDPDK
DPDK
 
HTTP 완벽가이드 : 1-1 http 개관
 HTTP 완벽가이드 : 1-1 http 개관 HTTP 완벽가이드 : 1-1 http 개관
HTTP 완벽가이드 : 1-1 http 개관
 
HTTP 완벽가이드 4장 커넥션관리
HTTP 완벽가이드 4장 커넥션관리HTTP 완벽가이드 4장 커넥션관리
HTTP 완벽가이드 4장 커넥션관리
 
[HTTP 101] 웹 개발자라면 반드시 알아야하는 HTTP의 기초
[HTTP 101] 웹 개발자라면 반드시 알아야하는 HTTP의 기초[HTTP 101] 웹 개발자라면 반드시 알아야하는 HTTP의 기초
[HTTP 101] 웹 개발자라면 반드시 알아야하는 HTTP의 기초
 
ACL - cisco 2811 router
ACL - cisco 2811 router ACL - cisco 2811 router
ACL - cisco 2811 router
 

Ähnlich wie 소켓프로그래밍 기초요약

Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client
문익 장
 
05 1 통신프로토콜과표준화-최근표준화협력방향
05 1 통신프로토콜과표준화-최근표준화협력방향05 1 통신프로토콜과표준화-최근표준화협력방향
05 1 통신프로토콜과표준화-최근표준화협력방향
Youngsun Lee
 
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
KH Park (박경훈)
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디
quxn6
 

Ähnlich wie 소켓프로그래밍 기초요약 (20)

Block chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overviewBlock chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overview
 
Implementing remote procedure calls rev2
Implementing remote procedure calls rev2Implementing remote procedure calls rev2
Implementing remote procedure calls rev2
 
Cse342 chapter 04
Cse342 chapter 04Cse342 chapter 04
Cse342 chapter 04
 
웹기반원격감시제어 2010 CPD
웹기반원격감시제어 2010 CPD웹기반원격감시제어 2010 CPD
웹기반원격감시제어 2010 CPD
 
Interface and Protocol
Interface and ProtocolInterface and Protocol
Interface and Protocol
 
초보자를 위한 네트워크/VLAN 기초
초보자를 위한 네트워크/VLAN 기초초보자를 위한 네트워크/VLAN 기초
초보자를 위한 네트워크/VLAN 기초
 
Python으로 채팅 구현하기
Python으로 채팅 구현하기Python으로 채팅 구현하기
Python으로 채팅 구현하기
 
네트워크와 인터넷
네트워크와 인터넷네트워크와 인터넷
네트워크와 인터넷
 
L4교육자료
L4교육자료L4교육자료
L4교육자료
 
[NodeJS] - NET 모듈 소개
[NodeJS] - NET 모듈 소개[NodeJS] - NET 모듈 소개
[NodeJS] - NET 모듈 소개
 
Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client
 
Network virtualization for the better understanding of Data Center Network
Network virtualization for the better understanding of Data Center NetworkNetwork virtualization for the better understanding of Data Center Network
Network virtualization for the better understanding of Data Center Network
 
KGC 2014: 클라이언트 개발자를 위한 컴퓨터 네트워크 기초 배현직
KGC 2014: 클라이언트 개발자를 위한 컴퓨터 네트워크 기초 배현직KGC 2014: 클라이언트 개발자를 위한 컴퓨터 네트워크 기초 배현직
KGC 2014: 클라이언트 개발자를 위한 컴퓨터 네트워크 기초 배현직
 
ice_grad
ice_gradice_grad
ice_grad
 
TCP 연결 과정_Wh apm
TCP 연결 과정_Wh apmTCP 연결 과정_Wh apm
TCP 연결 과정_Wh apm
 
05 1 통신프로토콜과표준화-최근표준화협력방향
05 1 통신프로토콜과표준화-최근표준화협력방향05 1 통신프로토콜과표준화-최근표준화협력방향
05 1 통신프로토콜과표준화-최근표준화협력방향
 
DGMIT 제3회 R&D 컨퍼런스 r&d1 team : HTTP 프로토콜 개요
DGMIT 제3회 R&D 컨퍼런스 r&d1 team : HTTP 프로토콜 개요DGMIT 제3회 R&D 컨퍼런스 r&d1 team : HTTP 프로토콜 개요
DGMIT 제3회 R&D 컨퍼런스 r&d1 team : HTTP 프로토콜 개요
 
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
3일차-닷넷 분산 기술의 이해 (인피니트 강의자료)
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디
 
Netmanias L2,L3 Training (5) L3 SW Architecture
Netmanias L2,L3 Training (5) L3 SW ArchitectureNetmanias L2,L3 Training (5) L3 SW Architecture
Netmanias L2,L3 Training (5) L3 SW Architecture
 

Mehr von 세빈 정 (7)

Gpg study3.7
Gpg study3.7Gpg study3.7
Gpg study3.7
 
Gpg study1.8
Gpg study1.8Gpg study1.8
Gpg study1.8
 
Effective c++ Chapter6
Effective c++ Chapter6Effective c++ Chapter6
Effective c++ Chapter6
 
Effective c++ 1,2
Effective c++ 1,2Effective c++ 1,2
Effective c++ 1,2
 
디자인 패턴(Observer, visitor)
디자인 패턴(Observer, visitor)디자인 패턴(Observer, visitor)
디자인 패턴(Observer, visitor)
 
Pac-man
Pac-manPac-man
Pac-man
 
포스트모템1
포스트모템1포스트모템1
포스트모템1
 

Kürzlich hochgeladen

Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
Wonjun Hwang
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
Wonjun Hwang
 

Kürzlich hochgeladen (6)

MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 

소켓프로그래밍 기초요약

  • 1. TCP/IP 소켓 프로그래밍 기초 - windows 위주로 네트워크 프로그래밍과 소켓의 이해 1. 간단한 이해 네트워크 프로그래밍이란 네트워크로 연결되어 있는 서로 다른 두 컴퓨터가 데이터를 주 고 받을 수 있도록 하는 것이다. 오늘날 대부분의 컴퓨터는 인터넷이라는 거대한 네트워크로 연결 되어 있다. 이러한 물 리적 연결된 네트워크상에서의 데이터 송수신에 사용할 수 있는 소프트웨어적인 장치를 ‘소켓’ 이라고 한다. 즉, 프로그래밍에서의 ‘소켓’은 네트워크 망의 연결에 사용되는 도구이다. 2. 전화 받는 소켓의 구현 소켓 중 TCP소켓이 전화기에 비유가능, 전화는 거는 것과 받는 것이 모두 가능하지만 소 켓은 <거는 용도>의 소켓과 <받는 용도>의 소켓이 따로 존재한다. i) 소켓 생성 함수  전화 받는 소켓을 생성, 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 반환  이제 전화번호를 받아야 한다. ii) 전화번호에 해당되는 ip와 포트번호라는 소켓의 주소정보를 할당 소켓에 주소 정보를 할당, 성공 시 0, 실패 시 SOCKET_WRROR 반환  이제 전화 케이블에 연결해 수신이 가능하게 해야 한다. iii) 소켓에 연결요청이 가능한 상태로 전환 소켓을 연결요청을 받을 수 있는 상태로 전 환, 성공 시 0, 실패 시 SOCKET_ERROR 반환  이제 전화 요청이 왔을 때 요청을 수락할 수 있게 해줘야 한다. iv) 연결 요청이 들어오면 수락하는 함수  소켓에 연결 요청이 들어오면 수락, 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 반환 지금까지의 내용을 요약 하자면 네트워크 프로그래밍 에서 연결요청을 허락하는 소켓 생 성과정을 다음 과 같이 정리할 수 있다.
  • 2. 1. 소켓 생성 – socket 함수호출 2. IP주소와 PORT번호 할당 - bind 함수호출 3. 연결요청 가능상태로 변경 – listen 함수호출 4. 연결요청에 대한 수락 – accept 함수호출 이러한 연결요청을 수락하는 기능을 가진 프로그램을 ‘서버(server)’ 라고 한다. 이 과정에서 생성한 소켓을 가리켜 ‘서버 소켓’ 또는 ‘리스닝 소켓’ 이라 한다. 3. 전화 거는 소켓의 구현 전화를 거는 소켓은 연결요청을 진행하는 ‘클라이언트 소켓’ 이다. i) 클라이언트 프로그램에서는 socket 함수호출을 통한 소켓의 생성과 connect 함수호출을 통한 서버로의 연결요청 과정만이 존재한다.  클라이언트 프로그램에서 소켓을 기반으로 연결요청을 하는 함수, 성공 시 0, 실패 시 SOCKET_ERROR를 반환 4. Windows 에서의 소켓프로그래밍 특징 i) 헤더파일 winSock2.h를 포함, ws2_32.lib 라이브러리를 링크시켜야 한다. ii) 윈속(winsock)의 초기화 윈속 프로그래밍을 할 때에는 반드시 WSAStartup 함수호출로, 프로그램에서 요구하는 윈도우 소켓의 버전을 알리고 해당되는 라이브러리의 초기화 작업을 진행해야 한다. 1) wVersionRequested  프로그래머가 사용할 윈속의 버전정보 전달 이 첫 번째 인자에는 상위 8비트에는 주 버전을 하위 8비트에는 부 버전 정보를 전달한다. Ex) 사용할 버전이 1.2라면 MAKEWORD(1, 2)를 입력  0x0201 반환 2) lpWSAData  WSADATA라는 구조체 변수의 주소 값 전달 iii) 초기화된 라이브러리의 해제 방법  할당된 윈속 라이브러리가 윈도우 운영체제에 반환 되면서, 윈속관련 함수의 호출이 불가능하게 만든다. iv) Windows에서의 파일 핸들과 소켓 핸들 리눅스와는 달리 윈도우에서는 파일 핸들과 소켓 핸들을 구분한다. 윈도우 에서는 정수로 표현되는 소켓의 핸들 값 저장을 위해서 typedef 선언으로 정의된 새로운 자료 형인
  • 3. SOCKET이라는 변수를 사용한다. 이러한 차이가 나는 이유는 기본적으로 두 운영체제의 커널은 구조적으로 차이가 있고, 각각 구현 스타일도 다르기 때문이다. 5. Windows 기반 입출력 함수 리눅스에서는 소켓도 파일로 간수하기 때문에, read와 write를 이용해서 데이터를 송수신할 수 있다. 그러나 윈도우는 구분이 되어있기 때문에 소켓 기반의 입출력 함수가 존재한다. i)  성공 시 전송된 바이트 수, 실패 시 SOCKET_ERROR 반환, 리눅스의 write함수와 마지막 인자를 제외하면 비슷함, 마지막 인자에는 옵션이 없다는 것을 의미하여 0을 보통 사 용 ii)  성공 시 수신한 바이트 수(EOF  0), 실패 시 SOCKET_ERROR 반환 소켓의 타입과 프로토콜의 설정 1. 프로토콜 이란? 멀리 떨어져있는 두 사람이 대화를 주고받기 위해서는 나름의 대화방법이 필요하다. 예를 들어 한 사람이 전화를 할 때 한 사람이 편지를 쓸 수는 없는 일이다. 이 때의 두 사람의 대화에 사용한 프로토콜은 전화라고 할 수 있다. 이렇듯 프로토콜 이란 대화에 필요한 ‘통신규약’을 의미한다.  “컴퓨터 상호간의 대화에 필요한 통신규약” 2. 소켓의 생성 af  소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달 type  소켓의 데이터 전송방식에 대한 정보 전달 protocol  두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달 앞에서 언급하지 않았던 각각의 매개변수에 대한 자세한 설명이다. 3. 프로토콜 체계(Protocol Family) 소켓이 통신에 사용하는 프로토콜도 부류가 나뉜다. 그리고 socket 함수의 첫 번 째 인자로, 생성되는 소켓이 사용할 프로토콜의 부류정보를 전달한다. 이러한 부류정보를 가리켜 ‘프로토콜 체계’라 한다.
  • 4. 이름 프로토콜 체계 PF_INET IPv4 인터넷 프로토콜 체계 PF_INET6 IPv6 인터넷 프로토콜 체계 PF_LOCAL 로컬 통신을 위한 UNIX 프로토콜 체계 PF_PACKET Low Level 소켓을 위한 프로토콜 체계 PF_IPX IPX 노벨 프로토콜 체계 가장 보편화된 프로토콜 체계는 PF_INET이다. 실제 소켓이 사용할 최종 프로토콜 정보는 첫 번째 인자를 통해 지정한 프로토콜 체계 안에 존재하는 것 중 하나를 세 번째 인자에 넣어 결정한다. 4. 소켓의 타입 소켓의 타입이란 소켓의 데이터 전송방식을 의미하는데, 이 정보를 socket 함수의 두 번째 인자로 전달한다. 첫 번째 인자로 프로토콜 체계 정보를 입력하긴 하 지만 한 프로토콜 체계에서도 둘 이상의 데이터 전송방식이 존재하기 때문에 따 로 인자를 넣어줘야 한다. 다음은, 가장 대표적인 데이터 전송방식 2가지를 소개하겠다. i) 연결지향형 소켓(SOCK_STREAM) : 독립된 하나의 라인을 통해 데이터를 주고받음  소켓 대 소켓의 연결은 반드시 1대 1 1) 독립된 별도의 전송라인을 통하기 때문에 라인에 문제만 없다면 데이터가 소 멸되지 않음을 보장받을 수 있다.  중간에 데이터가 소멸되지 않고 목적지로 전송된다. 2) 데이터는 전송라인에 올려진 순서대로 데이터가 전달된다.  전송 순서대로 데이터가 수신된다. 3) 데이터의 경계가 존재하지 않음은 다음의 상황을 표현한 것이다.  전송되는 데이터의 경계(Boundary)가 존재하지 않는다. “데이터를 전송하는 컴퓨터가 세 번의 send 함수호출을 통해서 총 100바이트를 전송 하였다. 그런데 데이터를 수신하는 컴퓨터는 한 번의 recv 함수호출을 통해서 100바이트 전부를 수신하였다.” 데이터를 송수신하는 소켓은 내부적으로 buffer배열을 가지고 있다. 그리고 소켓을 통해 전송되는 데이터는 일단 이 배열에 저장된다. 배열의 용량을 초과 하지
  • 5. 않는 한, 데이터가 채워진 후 한번의 recv 함수호출로 받아올 수도 있고, 반대로 여러 번의 recv 함수 호출로 받아올 수도 있다. 즉, send 함수와 recv 함수 호출 횟수는 연결지향형 소켓에서는 큰 의미를 갖지 못한다. 그래서 연결지향형 소켓은 데이터의 경계가 존재하지 않는다고 말하는 것이다. +버퍼가 꽉 채워지면? 연결지향형 소켓은 자신과 연결된 상대 소켓의 상태를 파악하면서 데이터를 전송 하기 때문에 꽉 차있다면 데이터를 수신 하지 않는다. 그리하여 데이터가 소멸되는 일은 발생하지 않는다. i ) 비 연결지향형 소켓(SOCK_DGRAM) : 오토바이 택배 서비스에 비유  연결이라는 개념 존재x 1) 출발순서에 상관없이 최대한 빨리 목적지를 향함  전송된 순서에 상관없이 가장 빠른 전송을 지향한다. 2) 택배는 그 특성상 손실 및 파손의 우려가 있다.  전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있다. 3) 오토바이에 실어서 보낼 수 있는 물건의 크기도 제한된다.  한번에 전송할 수 있는 데이터의 크기가 제한된다. 4) 택배 물건이 2개가 오면 2번에 걸쳐 수령해야 한다.  전송되는 데이터의 경계(boundary)가 존재한다. 정리하자면, “신뢰성과 순차적 데이터 전송을 보장하지 않는, 고속의 데이터 전송을 목적으로 하는 소켓” 5. 프로토콜의 최종선택(세 번째 인자) 사실 앞에서 설명했던 ‘프로토콜 체계’와 ‘데이터 전송방식’에 대한 정보만 주어지고 세 번째 인자는 0으로 주어져도 소켓을 생성할 수 있다. 그렇다면 왜 세 번째 인자가 필요한가 하면 다음과 같은 상황 때문이다. “하나의 프로토콜 체계 안에 데이터의 전송방식이 동일한 프로토콜이 둘 이상 존 재하는 경우” 이런 경우 세 번째 인자를 통해서 원하는 프로토콜의 정보를 조금 더 구체화 하
  • 6. 는 것이다. 주소체계와 데이터 정렬 1. 인터넷 주소 인터넷에 연결하려면 IP주소를 부여 받아야 한다. 이러한 IP주소 체계는 다음과 같이 두 종류로 나뉜다. -IPv4(Internet Protocol version 4)  4바이트 주소체계 -IPv6(Internet Protocol version 6)  16바이트 주소체계 이 2가지 주소체계의 차이는 표현에 사용되는 바이트 크기에 있다. IPv6는 현재에도 거의 안 쓰이므로 생략. IPv4 기준의 4바이트 IP주소는 네트워크 주소와 호스트 주소로 나뉘며 주소의 형 태에 따라 클래스가 나뉜다. 네트워크 주소 – 네트워크 구분을 위한 IP주소의 일부 네트워크 주소를 입력하여 해당 네트워크로 데이터가 전송된 후에 라우터가 호스트 주소를 기반으로 해당되는 호스트에 데이터를 보내는 방식이다. 2. 클래스 별 네트워크 주소와 호스트 주소의 경계 IP주소의 첫 번째 바이트만 보면 네트워크 주소가 몇 바이트인지 판단이 가능하다. 왜냐하면 클래스 별 IP주소의 경계를 나눠놓았기 때문이다. (위의 표 참조) 혹은 이렇게 표현되기도 한다. - 클래스 A의 첫 번째 비트는 항상 0으로 시작 - 클래스 B “ 10으로 시작 - 클래스 C “ 110으로 시작 이렇게 기준이 있기 때문에 네트워크로 데이터가 이동할 때 신경 쓰지 않아도 된 다. 3. 소켓의 구분에 활용되는 PORT번호 IP는 컴퓨터를 구분하기 위한 목적으로 존재해서 IP를 가지고 목적지 컴퓨터만 알 수 있지 최종 목적지인 응용프로그램까지는 알 수가 없다. 최종 목적지를 알
  • 7. 려면 해당 소켓을 알아야 한다. 그렇다면 어떻게 소켓을 구분할까 우리의 컴퓨터에는 NIC(Network Interface Card)라 불리는 데이터 송수신장치가 하나씩 달려있다. IP는 데이터를 NIC를 통해 컴퓨터 내부로 전송한다. 그 후에 NIC에 수신된 데이터 안에 있는 PORT번호를 이용해서 운영체제가 해당 PORT번 호의 소켓에 데이터를 전달하는 것이다. 4. PORT번호의 특징 i) PORT번호는 소켓을 구분하는 목적으로 사용되므로 동일한 PORT번호는 1개만 존재할 수 있다. ii) 16비트로 표현되기 때문에 할당 가능한 범위는 0~65535 이다. iii) 0~1023까지는 ‘잘 알려진 PORT(Well-known PORT)’라 해서, 특정 프로그램에 할당하기로 예약되어 있기 때문에 이 영역은 할당에서 제외해야 한다. iv) TCP소켓과 UDP소켓은 PORT번호를 공유하지 않기 때문에 중복 가능하다. 5. IPv4 기반의 주소표현을 위한 구조체 i) sin_family 주소체계 정보를 저장한다. 주소체계 의미 AF_INET IPv4 인터넷 프로토콜에 적용하는 주소체계 AF_INET6 IPv6 인터넷 프로토콜에 적용하는 주소체계 AF_LOCAL 로컬 통신을 위한 유닉스 프로토콜의 주소체계 ii) sin_port 16비트 PORT번호를 저장한다. 단, ‘네트워크 바이트 순서’로 저장해야 한다.
  • 8. iii) sin_addr 32비트 IP주소정보를 저장한다. 이 역시 ‘네트워크 바이트 순서’로 저장해야 한다. iv) sin_zero 특별한 의미를 지니지 않는 멤버이다. 단순히 구조체 sockaddr_in 과 구조체 sockaddr의 크기를 일치시키기 위해 삽입된 멤버이다. 6. 바이트 순서와 네트워크 바이트 순서 CPU에 따라서 4바이트 메모리 공간에 저장하는 방식이 다를 수가 있다. 때문에 이러한 부분을 고려하지 않고서 데이터를 송수신하면 문제가 발생할 수 있다.  이것은 곧 데이터의 해석순서가 다름을 뜻하기 때문이다. CPU가 데이터를 메모리에 저장하는 방식은 다음과 같이 두 가지로 나뉜다.  데이터를 해석하는 방식도 두 가지로 나뉜다는 것을 의미한다. i) 빅 엔디안(Big Endian)  상위 바이트의 값을 작은 번지수에 저장하는 방식 ii) 리틀 엔디안(Little Endian)  상위 바이트의 값을 큰 번지수에 저장하는 방식 정수 0x12345678중 0x12가 최상위 바이트 0x78이 최하위 바이트이다. 따라서 빅 엔디안 방식은 0x12부터 순서대로 저장되고, 반대로 리틀 엔디안 방식은 0x78부 터 작은 번지수에 저장된다.  이렇게 CPU마다의 데이터 저장방식을 의미하는 것이 ‘호스트 바이트 순서’라 고 한다. 이 상황에서 서로 저장하는 방식이 다른 CPU끼리 데이터 송수신을 한다면 그 과 정에서 문제가 생길 것이다. 그래서, 이 문제를 해결하기 위해 통일된 기준으로 네트워크를 사용하기로 했으며 그것이 ‘네트워크 바이트 순서’라 한다. 네트워크 바이트 순서  빅 엔디안 방식으로의 통일 7. 바이트 순서의 변환 i)바이트 변환을 돕는 함수 h는 호스트(host) 바이트 순서를 의미, n은 네트워크 바이트 순서를 의미
  • 9. 그리고 s는 short, l은 long을 의미한다. 일반적으로 s가 붙는 함수는 PORT번호의 변환에 사용되고, l이 붙은 함수는 IP주소의 변환에 사용된다. +그렇다면 데이터 전송하기 전에 항상 바꿔줘야 하나?  sockaddr_in 구조체 변수에 데이터를 채울 때 이외에는 바이트 순서를 신경 쓰지 않아도 된다! 8. 문자열 정보를 네트워크 바이트 순서의 정수로 변환하기 sockaddr_in 안에서 주소정보를 저장하기 위해 선언된 멤버는 32비트 정수형으로 정의 되어 있다. 따라서 “211.214.107.99”와 같이 점이 찍힌 십진수 표현의 문자열을 32비트 정수형으로 변환해줘야 한다. 그리고 이를 위한 함수가 존재한다. 성공 시 빅 엔디안으로 변환된 32비트 정수 값, 실패 시 INADDR_NONE 반환 위의 함수와 반대되는 기능을 하는 함수도 존재한다.  정수형태의 IP정보를 참조하여 문자열 형태의 IP정보로 변환해서 문자열의 주 소 값을 반환 한다. 주의할 점은 반환형이 char형 포인터라는 것이다. 주소 값을 반환한다는 것은 이 미 문자열이 메모리 공간엔 저장되어있음을 뜻하는데, 위 함수에서는 내부적으로 메모리공간 할당을 요청하지 않으므로 함수 호출 뒤에도 문자열 정보를 오랫동안 저장하고 싶다면 메모리 공간을 할당하는 것이 좋다. 9. 인터넷 주소의 초기화 지금까지 살펴본 내용을 기반으로 소켓생성과정에서 흔히 등장하는 인터넷 주소정보의 초기화 방법이다. memset으로 구조체 addr을 초기화 하였는데 그 이유는 sin_zero를 0으로 초기화 하기 위함이다.  위 과정은 서버 프로그램에서 주로 등장한다 .
  • 10. 10. 클라이언트 주소정보 초기화 클라이언트 프로그램에서는 connect함수를 통해서 자신을 전달한다. Sockaddr_in 구조체 변수를 선언해 이를 연결할 서버 소켓의 IP와 PORT번호로 초기화한 다음에 connect함수를 호출한다. 11. INADDR_ANY 서버 소켓의 생성과정에서 매번 서버의 IP주소를 입력하는 것은 비효율적이다. 이 때 다음과 같이 주소정보를 초기화 가능하다.  소켓이 동작하는 컴퓨터의 IP주소가 자동으로 할당된다. TCP 기반 서버/클라이언트 1 :데이터 전송 방법에 따라서 TCP 소켓과 UDP 소켓으로 나뉘고, TCP 소켓의 경우 연결을 지향하여 ‘스트림 기반 소켓’이라고도 이야기한다. 1. TCP/IP 프로토콜 스택 위 그림은 데이터 송수신의 과정을 네 개의 영역으로 계층화했다는 의미로 받아들일 수 있다.  ‘인터넷 기반의 효율적인 데이터 전송’이라는 문제를 계층화 하 여 해결한 것이다.
  • 11. i) LINK 계층  물리적 연결에 대한 표준 : 물리적인 영역의 표준화에 대한 결과이다. 이는 가장 기본이 되는 영역으로 LAN, WAN, MAN과 같은 네트워크 표준과 관련된 프로토콜을 정의하는 영역이다. 바로 이 부분에서의 물리적인 연결을 LINK계층이 담당한다. ii) IP 계층  데이터 전송을 위한 경로 지정 프로토콜 : 데이터를 목적지까지 보낼 경로를 선택하는 것이 IP계층이다. 이 계층에서 사용하는 프로토콜이 IP이다. IP의 특징은 비 연결지향적이며 신뢰할 수 없다는 것이다. 경로가 일정치 않 고, 경로를 변경할 때 데이터 손실이나 오류를 해결하지 못한다. 즉, 오류에 취약하다. iii) TCP/UDP 계층  IP에서 제공한 경로를 바탕으로 데이터 실 제 송수신을 담당 : IP계층에서 알려준 경로정보를 바탕으로 데이터의 실제 송수신을 담당한다. 때문에 이 계층을 가리켜 ‘전송계층’ 이라 한다. 그런데 TCP가 데이터를 보낼 때 기반이 되는 프로토콜이 IP이다. IP는 오로지 하나의 데이터 패킷이 전송되는 과정에만 중심을 두고 설계되어서 여러 개의 데이터 패킷을 전송할 때 오류를 인식 할 수가 없다. TCP 프로토콜은 이러한 오류를 해결해 준다.  TCP는 확인절차를 걸쳐서 신뢰성 없는 IP에 신뢰성을 부여한 프로토콜이라 할 수 있다. iv) APPLICATION 계층 : 최종적으로 소켓이라는 도구가 주어졌고, 이 도구를 이용해서 무엇인가를 만들면 프로그램의 성격에 따라 클라이언트와 서버간의 데이터 송수신에 대 한 약속이 정해지는데, 이를 가리켜 APPLICATION 프로토콜 이라한다. 네트워크 프로그래밍은 대부분 APPLICATION 프로토콜이 상당부분을 차지한다.
  • 12. 2. TCP기반 서버에서의 기본적인 함수호출 순서  연결대기 상태로의 진입을 위한 함수 여기서는 ‘연결요청 대기상태’의 의미와 ‘연결요청 대기 큐’라는 것에 대해서 설명할 것이다. 클라이언트의 연결요청도 인터넷을 통해서 흘러 들어오는 일종의 데이터 전송이기 때문에, 이것을 받는 소켓이 하나 있어야 한다. listen함수가 호출되면, 서버 소켓이 만들어지고 두 번째 인자로 전달되는 정수의 크기에 해당되는 대기실이 만들어진다.  ‘연결요청 대기 큐’ 3. 클라이언트의 연결요청 수락 listen 함수호출 이후에 클라이언트의 연결요청이 들어왔다면, 들어온 순서대로 수락을 한다. 연결을 한다는 것은 곧 데이터를 주고받는 것을 의미하는데 이 때 소켓이 필요하다. 하지만 서버 소켓은 요청을 받는 역할을 하고 있으므로 소켓을 하나 더 만들어야 한다. 그러기 위한 함수가 바로 accept 함수이다. 클라이언트의 서버로의 연결요청은
  • 13. 위 connect 함수호출을 통해 하게 되는데 이 때 1) 서버에 의해 연결요청이 접수되거나 2) 오류로 인한 중단이 되었을 때 함수가 반환된다. 이 때 주의할 점은 1)의 상황이라 해서 서버의 accept 함수호출을 의미하는 것은 아니라는 점이다. 단지 서버의 연결요청 대기 큐에 등록된 상황을 의미할 수도 있다. 4. Iterative 서버의 구현 accept 함수가 호출된 다음에 입출력 함수를 호출하고 있다. 그리고 이어서 close 함수를 호출하는데 이는 서버 소켓이 아니라, accept 함수의 호출로 생성된 소켓을 대상으로 하는 것이다. +그럼 서버라는 것이 한 순간에 하나의 클라이언트만 연결하는 건가? 이는 후에 프로세스와 쓰레드에 대해 공부하고 나면 둘 이상의 클라이언트에 연결하는 서버를 만들 수 있게 된다.
  • 14. 소켓의 우아한 연결종료 1. 일방적인 연결종료의 문제점 윈도우의 closesocket 함수호출은 완전종료를 의미한다.  이 말은 곧, 데이터 전송과 수신이 불가능하다는 것을 의미한다. 두 개의 호스트가 연결된 상황에서 한 쪽이 closesocket함수를 호출하면 두 호스 트 간의 데이터 송수신이 불가능해 진다. 이 때, 한 쪽이 데이터 전송 후에 다른 쪽이 closesocket을 해버리면 데이터가 소멸되고 마는 문제가 발생한다.  이를 위한 해결책으로, 스트림의 일부만 종료하는 ‘Half-close’방법이 제공되고 있다. 전송과 수신 둘 중 한가지를 종료하는 것으로 스트림의 반만 닫는 것이다. 2. 소켓과 스트림 소켓을 통해 두 호스트가 연결되면, 데이터 송수신이 가능하게 된다. 이러한 상태 를 ‘스트림이 형성된 상태’라고 한다. 스트림은 한쪽 방향으로만 형성되기 때문에 양방향 통신을 위해서는 두 개의 스트림이 필요하다. 우아한 종료라는 것은 이 중 하나의 스트림만 끊는 것을 말한다. 3. 우아한 종료를 위한 shutdown 함수 Half-close에 사용되는 함수에는 shutdown 함수가 있다. 성공 시 0, 실패 시 SOCKET_ERROR 반환 위 함수의 두 번째 매개변수에 전달되는 인자와 그 의미는 다음과 같다. - SD_RECEIVE  입력 스트림 종료 - SD_SEND  출력 스트림 종료 - SD_BOTH  입출력 스트림 종료 입력 스트림을 종료하면 이후에 입력버퍼에 전달되는 데이터는 지워지 만, 출력
  • 15. 스트림을 종료한 후에 출력 버퍼에 아직 전송되지 못한 데이터가 존재하면 해당 데이터는 목적지로 전송된다. 4. Half-close의 필요성 shutdown 함수호출의 필요성을 상황 별로 보면 알기 쉽다. i) 급히 종료하지 않으면 되지 않나 맞는 말이다. 이런 상황에선 굳이 Half-close를 하지 않아도 된다. 하지만 다음 상황을 보자 ii) 클라가 서버로부터 파일은 받고, 수신완료의 메시지를 주고 종료 하 려 한다. 클라 입장에서는 서버로부터 파일을 언제까지 받아야 하는지를 알 수 없 기 때문에 메시지를 주기 위해 무작정 기다려야 한다. 하지만 이렇게 무작 정 기다리다 보면 블로킹 상태에 빠질 위험이 있기 때문에 좋지 않다. iii) 파일의 끝은 의미하는 EOF를 보내주면 되지 않나 그러면 된다. 그렇다면 어떻게 서버는 클라에게 EOF를 보내줄 수 있는가 iv) 출력 스트림을 종료하면 상대 호스트로 EOF가 전송된다. closesocket 함수호출을 통해서 입출력 스트림을 모두 종료해주어도 EOF는 전송되지만, 이럴 경우 클라이언트가 서버에 보낼 데이터가 남아 있더 라도 전송 할 수 없게 된다. 이럴 경우에 EOF도 전송되고 입력스트림은 여전히 살아있어서 데이터 의 수신도 가능케 하는 Half-close함수 shutdown을 호출해주어야 하는것 이다.