TCP / IP 소켓 프로그래밍 1주차 ( 스터디 계획 및 Ch.1 ~ Ch.4 )
스터디 교재 및 방향 교재 방향 윤성우의 열혈 TCP/IP 소켓 프 로그래밍 (윤성우 저) Part1 ~ Part 2 4주 채팅 프로그래밍 2주 8주 스터디 교재로는 윤성우의 열혈 TCP/IP 소켓 프로그래밍이라는 책을 선정했고 스터디 방향은 Part1~2 4주, Part3~4 2주, 채팅 프로그래밍 2주해서 총 8주 계획을 했습니다.
세부 계획 스터디 계획 및 Ch.1 ~ Ch.4 1주차 Ch.5 ~ Ch.10.2 2주차 Ch.10.3 ~ Ch.14 3주차 4주차 기말고사 Ch.18 5주차 기말고사 Ch.19 ~ Ch.24 6주차 채팅 프로그래밍 7주차 8주차 스터디 세부 계획은 다음과 같습니다. 4~5주차는 기말고사 기간으로 잡고 공부 양을 줄이는 쪽으로 계획했습니다.
채팅 프로그래밍 7 ~ 8주차 기본 사용 언어 : C C 선택 시 윈도우나 리눅스 환경 중 택 1 선택 사항 : C 이외의 언어, GUI 채팅 프로그래밍은 7~8주차에 수행하고자 합니다. 기본 사용 언어는 C언어 이고 윈도우나 리눅스 환경 중 하나를 선택해서 할 것입니다. 개인 선택사항으로는 C언어 이외의 언어나 GUI 가 있습니다.
스터디 수행 환경 윈도우 리눅스 WMWARE 가상 리눅스 Visual Studio Cygwin Ws2_32.lib 라이브러리를 링 크시켜 사용 WMWARE 가상 리눅스 Cygwin 스터디 수행 환경은 다음과 같습니다. 윈도우 경우는 비주얼 스튜디오로 수행하고 리눅스 경우에는 VMWARE로 가상 리눅스를 돌려서 사용하거나 시그윈을 설치해서 사용했습니다.
Chapter 1 & 2 소켓의 이해와 타입 먼저 Ch. 1~2 소켓의 이해와 타입에 관한 내용입니다.
소켓이란 무엇인가? 네트워크 망의 연결에 사용되는 도구 연결요청을 수락하는 기능의 프로그램이 서버 Socket->bind->listen->accept->read/write->close(리눅스 기 준) 연결요청을 하는 프로그램이 클라이언트 Socket->connect->read/write->close(리눅스 기준) 소켓이란 네트워크 망의 연결에 사용되는 도구를 말하는데, 소켓을 사용하는 방법은 서버 프로그램과 클라이언트 프로그램이 있습니다. 서버 프로그램의 경우 다음과 같이 Socket 함수를 통해 소켓을 생성하고 bind 함수를 통해 IP와 PORT 번호를 할당하며 listen 함수로 연결 요청이 가능한 상태로 변경합니다. 이후 accept를 호출하여 대기중인 클라이언트의 요청을 받아들여 read/write 함수 등의 작업을 수행하고 close 함수를 통해 종료합니다. 클라이언트 프로그램은 서버 소켓의 생성과정에 비해 상대적으로 간단한데 socket 함수를 통해 소켓을 생성한 후 connect 함수를 수행해 연결 요청을 합니다. 그리고는 서버 프로그램과 같이 작업을 수행하고 종료됩니다.
리눅스와 윈도우 기반의 차이점 윈도우 소켓은 상당부분이 BSD계열 유닉스 소켓을 참 고하여 설계 리눅스 기반 네트워크 프로그램의 일부만 변경하면 실행 가능할 정도로 유사 윈도우는 헤더파일(wnisock2.h)과 라이브러리(ws2_32.lib) 을 추가 윈도우는 반드시 프로그램에 WSAStartup함수를 호출 윈도우는 파일과 소켓을 구분 리눅스와 윈도우의 소켓 프로그래밍의 차이점은 다음과 같습니다. 윈도우 소켓은 유닉스 소켓을 참고하여 설계되어 리눅스 기반 프로그램의 일부만 변경해도 실행이 가능할 수 있습니다. 또한 다음과 같은 헤더 파일과 라이브러리를 추가하여야 사용이 가능하며 반드시 프로그램의 함에 이 (WSAStartup)함수를 호출하여야 합니다. 그리고 윈도우는 리눅스와 달리 파일과 소켓을 구분해서 사용합니다.
소켓의 타입 연결지향형 소켓 (TCP) 비 연결지향형 소켓 (UDP) 중간에 데이터가 소멸되지 않고 목적지로 전송 중간에 데이터가 소멸되지 않고 목적지로 전송 전송 순서대로 데이터가 수 신 전송되는 데이터의 경계가 존재하지 않음 전송된 순서에 상관없이 가 장 바른 전송을 지향 전송된 데이터는 손실의 우 려가 있고 파손의 우려 존재 전송되는 데이터의 경계가 존재 한번에 전송할 수 있는 데이 터의 크기가 제한 소켓의 타입에는 다음과 같이 연결지향형 소켓과 비 연결지향형 소켓 이 있습니다. 연결지향형 소켓은 다음과 같은 신뢰성있는 순차적인 바이트 기반의 연결지향 데이터 전송 방식의 소켓이고 반면에 비 연결지향형 소켓은 신뢰성과 순차적 데이터 전송을 보장하지 않는, 고속의 데이터 전송을 목적으로 하는 소켓을 말합니다.
CHAPTER 3 주소 체계와 데이터 정렬 Ch. 3는 주소 체계와 데이터 정렬에 대한 내용입니다.
소켓에 할당되는 IP주소 인터넷주소란? 인터넷상에서 컴퓨터를 구분하는 목적으로 사용되는 주소. 4바이트 주소체계인 IPv4와 16바이트 주소체계인 IPv6가 존 재한다. 네트워크주소와 호스트주소로 나뉜다. 네트워크주소를 이용해서 네트워크를 찾고,호스트주소를 이용해서 호스트를 구분 한다. 인터넷 주소는 다음과 거대 인터넷 망에서 컴퓨터들 간에 서로를 구분하는 목적으로 사용되는 주소입니다. 주소 체계는 IPv4와 IPv6로 나누어져 있으며 IPv6는 IPv4의 고갈을 우려하여 만들어졌습니다. 아직까지는 IPv4가 주로 사용되고 있습니다. IPv4 같은 경우 네트워크 주소와 호스트 주로 나뉘는데 네트워크주소를 이용해서 네트워크를 찾고, 호스트주소를 이용해서 호스트를 구분 합니다. 이 그림에서 보시다 싶이 네트워크 주소를 통해 해당 라우터까지 이동을 하며 라우터에서 호스트 주소를 통해 해당 컴퓨터 데이터를 전송해줍니다.
소켓의 구분에 활용되는 PORT번호 PORT번호 <PORT번호에 의한 소켓의 구분과정> IP는 컴퓨터를 구분하는 용도로 사용되며, PORT번호는 소켓을 구 분하는 용도로 사용된다. PORT번호는 하나의 운영체제 내에서 동일한 PORT번호를 둘 이상 의 소켓에 할당할 수 없다. PORT번호는 16비트로 표현, 따라서 그 값은0 이상65535 이하 0~1023 은 잘 알려진 PORT(Well-known PORT)라 해서 이미 용도가 결 정되어 있다. <PORT번호에 의한 소켓의 구분과정> IP가 컴퓨터를 구분하는데 사용된다면, PORT번호는 하나의 운영체제 내에서 소켓을 구분하는 목적으로 사용됩니다. 따라서 동일한 PORT번호는 하나의 운영체제 내에서 둘 이상의 소켓에 할당할 수 없습니다. 그리고 PORT번호는 16비트로 표현, 그 값은 0 이상 65535 이하가 되며 0~1023은 잘 알려진 PORT이며 이미 용도가 결정되어 있습니다. 추가적으로 PORT번호는 중복이 불가능하지만, TCP소켓과 UDP 소켓은 PORT 번호를 공유하지 않기 때문에 중복되어 사용되어도 상관이 없습니다.
바이트 순서와 네트워크 바이트 CPU에 따라서 상위 바이트를 하위 메모리주소에 저장하기도 하고, 상위 바이트를 상위 메모리 주소에 저장 하기도 한다. 즉, CPU마다 데이터를 표현 및 해석하는 방식이 다르다. 네트워크 바이트 순서는 통일된 데이터 송수신 기준을 의미하며 빅 앤디안이 기준이다. 빅 앤디안 상위 바이트의 값을 작은 번지 수에 저장. 리틀 앤디안 상위 바이트의 값을 큰 번지수 에 저장. CPU는 바이트 저장 방식에 따라 빅 앤디안 머신과 리틀 앤디안 머신으로 나뉘는데 빅 앤디안 머신은 다음과 같이 상위 바이트 값을 작은 번지수에 저장하며 리틀 앤디안 머신은 상위 바이트의 값을 큰 번지수에 저장합니다. 네트워크 바이트 순서는 CPU의 바이트 저장 순서와 관계 없이 통일되게 빅 앤디안을 기준으로 동작합니다.
인터넷 주소의 초기화 일반적인 인터넷 주소의 초기화 과정 문자열로 표현된 IP주소와 PORT번호를 기반으로 하는 sockaddr_in 구 조체 변수의 초기화 과정을 보여주는 코드이다. 인터넷 주소는 다음과 같이 이 (sockaddr_in) 구조체 변수에 초기화 과정을 거치게 됩니다.
소켓에 인터넷 주소 할당하기 앞서 초기화 과정을 거친 구조체를 bind 함수에 넣어서 소켓에 IP와 PORT번호를 할당합니다. 추가적으로 클라이언트 프로그램은 bind 함수에 해당하는 역할을 connect 함수가 수행하며 운영체제에서 대신 자동으로 할당해줍니다.
INADDR_ANY INADDR_ANY : 소켓이 동작하는 컴퓨터의 IP주소의 상수 값 하지만 이와 같이 INADDR_ANY라는 이름의 상수를 통해서 서버의 IP주소를 할당하게 된다면 소켓이 동작하는 컴퓨터의 IP주소가 자동으로 할당 됩니다.
Chapter 4 Tcp 기반 서버/클라이언트 1 Ch. 4 에서는 TCP 기반의 서버와 클라이언트에 대해서 보게 됩니다.
TCP / IP 계층 목적지에 대한 경로 설정 물리적인 영역의 표준화 APPLICATION 계층 프로그램 성격에 따른 클라이언트와 서버간의 데이터 송수신에 대한 약속 TCP 계층 UDP 계층 경로 정보를 바탕으로 데이터의 실제 송수신 IP 계층 목적지에 대한 경로 설정 Routing 알고리즘 TCP / IP의 계층을 보면 다음과 같이 4개의 영역으로 구분할 수 있는데, LINK 계층은 물리적인 영역의 표준화 결과입니다. 그 예를 보게 된다면 다음과 같은 것들이 있습니다. IP계층의 경우는 목적지에 대한 경로를 설정하며 TCP/UDP 계층은 그 경로 정보를 바탕으로 실제 송수신을 하게 됩니다. Applcation 계층의 경우 프로그램 성격에 따른 데이터 송수신에 대한 약속이 정해집니다. LINK 계층 물리적인 영역의 표준화 Network 카드, LAN, WAN, MAN 등
TCP / IP 의 구조 TCP/IP의 구조를 보게 된다면 다음과 같이 데이터를 송신하는 HOST1의 하위 계층을 통과하되며 APPLICATION 계층 APPLICATION 계층 게이트웨이 및 라우터 TCP 계층 UDP 계층 TCP 계층 UDP 계층 IP 계층 IP 계층 IP 계층 TCP/IP의 구조를 보게 된다면 다음과 같이 데이터를 송신하는 HOST1의 하위 계층을 통과하되며 게이트 웨이 및 라우터를 통해 HOST2로 전송되어 상위 계층으로 올라가며 데이터가 수신되는 것을 볼 수 있습니다. LINK 계층 LINK 계층 및 물리적 계층 LINK 계층 서브 네트워크 서브 네트워크
TCP/UDP 란? IP의 상위계층에서 호스트 대 호스트의 데이터 송수신 방식 을 약속하는 것이 TCP / UDP TCP는 확인절차를 걸쳐서 신 뢰성 없는 IP에 신뢰성을 부여 함 앞서 연결 지향형 소켓과 비 연결 지향형 소켓의 설명에서 언급했었다 싶이 TCP의 경우 그림과 같이 확인절차의 수행을 통해서 신뢰성 없는 IP에 신뢰성을 부여해 줍니다.
계층화의 장점 표준화 작업을 통한 ‘개방형 시스템’의 설계를 가능하게 함. 표준화 작업을 통한 ‘개방형 시스템’의 설계를 가능하게 함. 표준이 존재하기에 빠른 속도의 기술 발전이 가 능하게 함. 개방형 시스템이란? 여러 개의 표준을 근거로 설계된 시스템 (예: TCP/IP 프로토콜) 개방형 시스템의 장점은? IP계층을 담당하는 라우터나 LINK계층을 담당하는 네트워크 카드를 교체해야 할 때 같은 모델이 아닌 타사의 제품을 가능하게 함. 앞서 보여드렸던 계층화에 대한 장점을 보게 된다면, 표준화 작업을 통한 ‘개방형 시스템’의 설계를 가능하게 하고 표준이 존재하기에 빠른 속도의 기술 발전이 가능하게 해줍니다. 개방형 시스템이란 여러 개의 표준을 근거로 설계된 시스템 뜻하며 그 개방형 시스템의 장점의 예를 보자면 IP계층을 담당하는 라우터나 LINK계층을 담당하는 네트워크 카드를 교체 해야될 경우에 같은 모델이 아닌 타사의 제품을 사용이 가능하게 함을 볼 수 있는데 이게 가능한 이유가 표준을 근거로 만들어지기 때문입니다.
listen 함수가 호출되면 클라이언트는 connect 함수를 호출할 수 있다. TCP 서버의 함수 호출 순서 listen 함수가 호출되면 클라이언트는 connect 함수를 호출할 수 있다. accept 함수가 호출되면 대기중인 클라이언트의 연결 요청을 수락한다 TCP 서버의 함수의 호출 순서는 앞서 서버 소켓의 생성에서 업급했듯이 다음과 같은 순서로 호출됩니다.
클라이언트에서는 connect 함수가 서버의 bind 함수와 같이 자동으로 IP와 PORT를 할당해준다. TCP 클라이언트의 함수 호출 순서 connect 함수를 호출하면 ‘연결 요청을 접수’할 수 있다. 클라이언트에서는 connect 함수가 서버의 bind 함수와 같이 자동으로 IP와 PORT를 할당해준다. TCP 클라이언트 또한 다음과 같은 순서로 호출됩니다.
TCP 기반 서버의 함수 호출 관계 connect 함수는 서버의 listen 함수가 호출되면 그 이후에 호출이 가능하다. 또한 connect 함수가 호출되기 전에 먼저 accept 함수가 호출 될 수 있다. (accept 함수 호출 이후 블로킹 상태) 위의 서버와 클라이언트 함수 호출간의 관계를 본다면 이와 같은데, connect 함수는 서버의 listen 함수가 호출되면 그 이후에 호출이 가능합니다. 또한 connect 함수가 호출되기 전에 먼저 accept 함수가 호출 될 수 있으며 이 경우 accept 함수 호출 이후 블로킹 상태가 됩니다.
Iterative 서버 Accept 함수를 통해서 대기중인 클라이언트와 연결하고 Read / write 를 수행 후 클라이언트를 종료한다 위를 반복 수행 한다. Iterative 서버는 이와 같이 accept 함수를 통해 대기중인 클라이언트와 연결하고 작업을 수행하는 부분에 반복문을 걸어 지속적으로 수행하는 서버입니다.
Echo 서버 if(listen(hServSock, 5)==SOCKET_ERROR) ErrorHandling("listen() error"); clntAdrSize=sizeof(clntAdr); for(i=0; i<5; i++) { hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize); if(hClntSock==-1) ErrorHandling("accept() error"); else printf("Connected client %d \n", i+1); while((strLen=recv(hClntSock, message, BUF_SIZE, 0))!=0) send(hClntSock, message, strLen, 0); closesocket(hClntSock); } Iterative 서버를 바탕으로 만들어진 예제 ECHO 서버를 보게된다면 다음과 같이 listen 함수를 호출한 후에 for문을 통하여 반복을 수행하게 됩니다.
Echo 클라이언트 Q or q 입력 시 종료 while(1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) break; send(hSocket, message, strlen(message), 0); strLen=recv(hSocket, message, BUF_SIZE-1, 0); message[strLen]=0; printf("Message from server: %s", message); } Echo 클라이언트 또한 While문 반복을 통해서 Q가 입력되기 까지 지속적으로 실행됨을 볼 수 있습니다.
Echo 서버/클라이언트 Echo Server 이를 수행하는 Echo 서버의 모습입니다. 위의 서버의 화면같이 클라이언트가 접속하면 접속을 표시하여주며 클라이언트는 작업을 수행하게 됩니다. Echo Client
Echo 서버/클라이언트2 Echo Server Echo Client 만약 두 개의 클라이언트가 동시에 접속하게 된다면 두 번째 클라이언트의 접속은 서버에 바로 표시 되지는 않으며 클라이언트가 전달한 문장에 대한 작업도 수행되지 않고 멈춰있습니다. Echo Client2
Echo 서버/클라이언트2 Echo Server Echo Client 첫 번째 클라이언트의 접속을 종료하게 되면 두 번째 클라이언트의 접속은 서버에 표시 되며 클라이언트가 전달한 문장에 대한 작업도 수행됩니다. Echo Client2
Echo 서버/클라이언트 문제점 TCP는 데이터 송수신간에 경계가 존재하지 않는다. Echo Client 한 번의 read 함수로 전송된 문자 열 전체를 읽어 들일 수 있다 가정 하고 있다. TCP의 경우 서버나 운영 체제가 문자열이 길다고 판단하면 여러 번에 나누어 보낼 수 있기에 일부 의 문자열만 읽힐 수 있다. Echo Client send(hSocket, message, strlen(message), 0); strLen=recv(hSocket, message, BUF_SIZE-1, 0); message[strLen]=0; printf("Message from server: %s", message); Echo Server 위에서 보였던 Echo 서버/클라이언트의 문제점을 보게 된다면 이와 같은 부분에 있는데 앞서서 보였다 싶이 TCP는 데이터 송수신간에 경계가 존재하지 않습니다. 하지만 위의 예제의 경우 한 번의 read 함수로 전송된 문자열 전체를 읽어 들일 수 있다 가정하고 있는데 TCP의 경우 서버나 운영 체제가 문자열이 길다고 판단하면 여러 번에 나누어 보낼 수 있기에 일부의 문자열만 읽힐 수 있는 문제점이 있습니다. while((strLen=recv(hClntSock, message, BUF_SIZE, 0))!=0) send(hClntSock, message, strLen, 0);