TCP 소켓이 생성되고 소멸하기까지 크게 나눠서 세 가지로 구분할 수 있습니다. - 상대 소켓과 연결 - 상대 소켓과 데이터 송수신 - 상대 소켓과의 연결 종료 먼저 소켓과의 연결 과정입니다. TCP 소켓은 연결 과정에서 총 세 번의 대화를 하는데, 이를 Three-way handshaking이라 합니다. 소켓은 전 이중 방식으로 동작하므로 양뱡향으로 데이터를 주고받을 수 있습니다. 따라서 데이터 송수신을 하기 이전에 준비가 필요한데, 먼저 연결요청을 하는 호스트 A가 B에게 [SEQ:1000 ACK:-]를 전달합니다. 여기서 SEQ 1000은 패킷의 번호가 1000이고, 잘 수신했다면 1001번 패킷을 전달하라고 말해달라는 뜻입니다. 처음 연결 요청에 사용되는 메시지여서 SYN(Synchronizati..
TCP
TCP소켓은 데이터 송수신의 경계가 없고, 데이터의 손실이 없습니다. 그러나 서버가 보낸 데이터보다 클라이언트가 받은 데이터가 적을 수도 있고, 그의 반대일 수도 있는데 아직 받지 않은 데이터는 어딨는건지 의문을 가질 수 있습니다. 데이터를 송신하는 쪽이 write 함수를 호출할 때 데이터가 출력버퍼로 이동하고, 데이터를 수신하는 쪽이 read 함수를 호출하면 입력 버퍼에 저장된 데이터를 읽어들이게 됩니다. 따라서 데이터를 보내면 먼저 출력버퍼에 전달되고, 상황에 맞춰 적당히 상대방의 입력버퍼로 전달됩니다. 특징을 정리하면 다음과 같습니다. - 입출력 버퍼는 TCP 소켓 각각에 대해 별도 존재 - 입출력 버퍼는 소켓생성시 자동으로 생성 - 소켓을 닫아도 출력버퍼에 남아있는 데이터는 계속해서 전송 - 소켓..
지금부터 구현할 서버와 클라이언트의 동작방식은 다음과 같습니다. - 클라이언트는 서버에 접속하자마자 피연산자의 개수 정보를 1바이트 정수형태로 전달 - 피연산자의 개수만큼 4바이트의 정수를 전달 - 정수를 전달한 다음, 1바이트 크기의 연산자의 종류 전달 (+,-,*) - 서버의 연산 결과를 4바이트 정수로 받아옴 - 연산 결과를 얻은 클라이언트는 서버와 연결 종료 클라이언트입니다. socket 생성, connect 호출까지는 똑같습니다. 선언되어 있는 변수와 매크로는 다음과 같습니다. #define BUF_SIZE 1024 #define RLT_SIZE 4 #define OPSZ 4 // 버퍼 크기, 결과 크기, 피연산자 크기 int sock; char opmsg[BUF_SIZE] // 서버에 보낼 문..
위 그림은 Iterative 서버의 함수호출 순서, TCP 서버-클라이언트 구현을 나타낸 것입니다. Iterative 서버란 반복문을 삽입해 accept 함수를 반복 호출해서 연결요청을 하는 모든 클라이언트에게 서비스를 제공하는 개념입니다. 클라이언트가 connect()로 연결요청을 하면 서버의 listen()에서 할당된 연결요청 큐에 추가됩니다. 서버는 들어온 연결요청을 하나하나 accept() 하고 서비스를 제공하고 close()로써 마무리하는 과정을 반복합니다. 이러면 한 번에 한 클라이언트에게만 서비스를 제공할 수 있게 되는데, 이는 프로세스와 쓰레드를 통해 다중 클라이언트에게 서비스를 제공하는 서버를 만들 수 있게 됩니다. echo란 입력한 문자열을 그대로 출력해주는 것(명령어 등)을 뜻합니다...
TCP/IP 프로토콜 스택은 위와 같이 네 개의 계층으로 나뉩니다. TCP 소켓을 이용할 땐 TCP 계층을 포함한 네 계층, UDP 소켓을 이용할 땐 UDP 계층을 포함한 네 계층을 통해 데이터를 송수신하게 됩니다. LINK 계층은 물리적인 영역의 표준화에 대한 결과로, LAN, WAN, MAN 등 네트워크 표준과 관련된 프로토콜을 정의하는 영역이며 가장 기본이 되는 영역입니다. 두 호스트가 데이터를 주고 받을 때 필요한 물리적인 연결부가 LINK 계층입니다. IP 계층은 목적지로 데이터를 전송하기 위해 어떤 경로를 거쳐갈 지를 해결하는 계층입니다. IP 계층에서 사용하는 IP 프로토콜은 데이터를 전송할 때마다 거쳐야 할 경로를 선택해주는데, 이 과정에서 데이터가 손실되는 등 오류가 발생할 시 이를 해결..
OS에 따라 자료형의 바이트 수가 바뀔 수 있습니다. 예를 들어 16비트 OS에서는 int는 2바이트임에 반해 32비트 OS에서는 4바이트를 가지고 있는 경우가 있습니다. (물론 같은 경우도 있고, 컴파일러에 따라 다르지만 OS의 비트와 int형의 비트수를 맞추는 경향이 있다고 합니다.) 그래서 다음은 이를 고려해서 4바이트 자료형이 항상 4바이트임을 보장받을 수 있도록 POSIX에서 정의한 자료형 입니다. 자료형 이름 자료형 정보 선언된 헤더파일 int8_t signed 8-bit int sys/types.h uint8_t unsigned 8-bit int (unsigned char) int16_t signed 16-bit int uint16_t unsigned 16-bit int (unsigned s..
앞서 우리는 클라이언트와 서버를 간략하게 짜보면서 sockaddr_in이라는 구조체를 사용했습니다. 이는 주소정보를 담기 위한 구조체입니다. 이 구조체는 다음과 같이 정의되어 있습니다. struct sockaddr_in{ sa_family_t sin_family; //주소 체계 uint16_t sin_port; //16비트 TCP/UDP PORT번호 struct in_addr sin_addr; //32비트 IP주소 char sin_zero[8]; //사용되지 않음(단, 0으로 채워줘야 함) } //위에서 사용된 struct in_addr은 다음과 같습니다. struct in_addr{ in_addr_t s_addr; //32비트 IPv4 인터넷 주소 } sin_family는 주소체계를 담습니다. 프로토콜..
IP주소 체계는 IPv4와 IPv6으로 나뉩니다. 각각 4바이트 주소체계, 16바이트 주소체계를 뜻하는데 오늘날엔 아직 IPv4를 대중적으로 사용하고 있습니다. (그래서 앞으로도 IPv4를 기준으로 말합니다) IPv4는 주소는 네트워크 주소와 호스트 주소로 나뉘어 있으며 형태에 따라서 A,B,C,D,E 클래스로 분류되는데, 여기서 E클래스는 일반적이지 않은(예약 되어있는) 클래스입니다. A,B,C,D 클래스의 구분은 다음과 같습니다. 클래스 A 1BYTE (네트워크 ID) 1BYTE*3(호스트 ID) 클래스 B 1BYTE*2 (네트워크 ID) 1BYTE*2(호스트 ID) 클래스 C 1BYTE*3 (네트워크 ID) 1BYTE(호스트 ID) 클래스 D 1BYTE*4 (멀티캐스트 IP주소) 첫 번째 바이트 범..