
위 그림을 이해하기 전 아래 그림을 먼저 본다.

Client가 SYN을 보내고 ACK을 받기 전까지의 시간을
SYN-SENT 라고 한다.
서버는 LISTEN에서 SYN을 받으면 자신의 SYN에 대한 ACK을
받을 때 까지를 SYN-RCVD라고 한다.
Data-Transfer가 일어나는 부분을 Established라고 표현한다.
이후 종류 Process를 보면, 일반적으로 4-Way Handshake를 통해 이루어지며 이것은 한쪽이 연결이 연결을 끊더라도 다른 쪽은 아직 보낼 데이터가 있을 수 있기 때문이다.
Active close를 요청하는 쪽에서 FIN을 보내고 FIN-WAIT1 상태가 된다.
ACK를 받으면 상대방의 FIN을 기다리는 FIN-WAIT2 상태가 되고 반대편은 CLOSE-WAIT상태가 된다. Active close를 요청한 쪽은 응답만 하는 상태가 된다.
이후 반대편에서 FIN을 보내면 ACK을 보내고 2MSL 동안 TIME-WAIT에 들어간다.
MSL은 Maximum Segment Lifetime의 줄임말로 네트워크 내에서 세그먼트가 존재 가능한 최대 시간을 의미하며 대략 1~2분정도 된다.
2 * MSL동안 기다리는 이유는 2가지가 있는데
첫번째는 마지막 ACK가 손실될 경우를 대비하여 Background에서 대기하는 것이다.
FIN에 대한 응답을 받지 못한채로 Client가 먼저 종료해버리면
서버는 계속 FIN을 보내면서 기다려야 한다.
따라서 ACK 손실에 대한 FIN 재전송을 받아주기 위해 남아있다.

두번째로는 바로 연결을 끊자마자 다시 연결을 한다고 가정해보자
파란선 위에서 보낸 패킷이 두 번째 연결이 체결되고 도착하면 새로운 연결의 유효한 패킷으로 잘못 해석될 수 있다.
따라서 2 * MSL동안 대기함으로써, 이전 연결에서 보낸 모든 지연 패킷이 네트워크 상에서 완전히 사라질 시간을 보장해주는 것이다.

TCP의 States 표이며 위의 설명과 함께 다시 맨 위 그림을 보면
이해할 수 있을 것이다.

서버에 동시 접속하는 예시를 보자
일단 클라이언트 1,2 는 같은 PC내의 다른 프로세스 이며 3은 다른 네트워크에 속해있다.
서버 시스템에서 기본 FD 0,1,2는 이미 할당되어 있으며 서버에서 연결만 받아주는 소켓이 80포트에 할당되어 있으며
FD는 3일 것이다.
이후 클라이언트1이 연결을 요청하면 서버소켓을 하나 생성하여 FD를 부여하고 어떤 클라이언트와 통신하는 것인지 테이블로 관리할 것이다.

모든 클라이언트는 서버의 80번 포트로 요청을 보내면
서버가 알아서 테이블을 통해 어떤 FD에 매칭시킬지 처리한다.
이런 서비스는 구현방식에 따라 단일 프로세스(멀티 쓰레드)
다중 프로세스(fork())로 구현될 수 있다.

TCP 서버의 함수 호출 기본 순서
bind 함수까지 호출이 되면 주소가 할당된 소켓이 된다.
SYN패킷을 받으면 SYN+ACK을 보내줄 수 있는 소켓이 되려면
listen함수를 통해 서버소켓으로 바꾸어줘야 한다.

우리가 사용할 소켓 2가지는
1. 일반소켓(클라이언트쪽, 데이터 송수신 용)
2. 서버소켓(SYN에 대한 응답가능한 소켓, listen으로 생성)

SYN패킷을 보낸 Client를 대기시킬 연결요청 대기 큐가 있다.
SYN-ACK에 대한 ACK이 오기 전까지 대기시킨다.

대기큐의 크기가 listen의 두번째 인자로 들어간다.

SYN-ACK에 대한 ACK이 오면 대기큐에서 꺼내어 클라이언트용 소켓을 만든다.
(accept return)
서버 소켓은 SYN만 받아주고 데이터 송수신은 accept의 리턴값인 소켓으로 한다.


connect함수가 SYN패킷을 보내는 역할을 한다



위 그림은 연결요청을 수락할 수는 있지만 동시에 둘 이상의 클라이언트에게 서비스를 제공할 수 있는 모델은 아니다.

클라이언트 코드의 일부

서버 코드의 일부
TCP는 데이터의 경계가 없기 때문에 read를 한번만 해서는 전체 다 읽을 수 없을 수도 있다.
이것의 수정된 버전은 이후에 다룬다.