5-1. 에코 클라이언트! TCP 기반에서의 완벽 구현
TCP 기반의 데이터 전송 특징
한 번의 데이터 전송함수 호출이 늘 하나의 패킷을 형성하는 것은 아니다.
※ 버퍼 : 서버 프로그램 상의 문자 배열.
※ ABCD를 클라이언트에서 서버로 보냈지만 A,B,C,D와 같이 패킷이 나누어져서 서버가 클라이언트로 보낼 수 있다.
※ echo server에서는 클라이언트에서 문제가 된다.
※ 구현 : 클라이언트는 여러번 read(recv)함수를 호출해야 한다. -> for문에서 읽어들인 바이트수가 보낸 바이스만큼 읽을 때까지 반복한다.
패킷이 나누어져 보내지는 이유? 뒤에 밝힘
5-2. 경계가 없는 TCP 기반의 데이터 전송
데이터 송수신 함수의 호출 회수는 큰 의미를 지니지 않는다.
예시) 위의 내용을 증명하기 위한 예제 프로그램
※ 서버에서는 한 번에 메세지를 읽기 위해서 sleep(5);를 한다.
※ 클라이언트에서는 4번에 나누어서 메세지 수신을 하기 위해 sleep(10);을 추가하였다.
이미 전송된 데이터는 어디에 존재하고 있었는가?
예시) 서버가 전송하면 클라이언트 (소켓)버퍼에 서버에서 받은 내용을 저장하고 있다.
서버에서 accept 했을 때 생기는 소켓에서 입력버퍼와 출력버퍼가 생성된다.
클라이언트는 소켓에 입출력버퍼가 있다.
※ read함수는 입력버퍼에 있는 내용을 읽는다. 바로 읽지 못할 수 있기 때문에 버퍼가 존재한다.
출력버퍼의 역할?
※ (서버에서) 송신할 때 (클라이언트의) 입력버퍼보다 큰 양을 보낼 수 없다.
=> 가능한 이유 : 클라이언트가 입력버퍼의 양만큼만 보내라는 신호를 보내기 때문에...
※ 이 이유때문에 출력(송신)버퍼가 필요하다.
※ 흐름제어를 위해서 입출력 버퍼가 존재한다.
TCP 기반의 전송제어
1. 버퍼가 수용할 수 있는 크기 이상의 데이터 전송은 이루어지지 않는다.
2. 따라서 TCP 기반의 데이터 전송 함수는 여러 개의 패킷을 생성하기도 한다.
3. 슬라이딩 윈도우 프로토콜 : 남은 버퍼양만큼만 데이터 전송을 하도록 돕는다.
5-3 TCP의 내부 구조
TCP의 데이터 전송 과정
(서버와 클라이언트는 서로 의견을 존중한다.)
1. 연결 설정 단계
클라이언트가 connect 함수 호출 시 진행
Three-way handshaking
① SYN(C) : 동기화. 싱크. 데이터를 주고 받을 수 있습니까?
② SYN + ACK(S) : 대화가 가능(OK)합니다. SYNchronize(동기화)에 대한 ACKnowgement(확인)의 기능.
③ ACK(C) : 잘 받았다라는 뜻으로 확인한다.
※ ③을 보내야 하는 이유 : 클라이언트가 ACK을 보내지 않으면 서버 입장에서 확인 메세지를 못받았다고 생각한다.
SEQ : 시퀀스 번호. 메세지를 잘 받았는 지 확인하기 위해서 붙이는 번호.
(메세지 번호) 내가 보낸 번호를 ACK으로 대답해 달라.
ACK : 확인 번호. 잘 받았다는 것을 응답하기 위해 붙이는 번호.
다음 SEQ 번호를 보내라는 뜻.
2. 데이터 송수신 단계
서버/클라이언트 간 데이터 송수신 함수 호출 과정에서 진행.
1. SEQ:1301,100바이트를 보낸다.
2. 100바이트를 잘 받았다는 것을 알리기 위해 SEQ번호+100을 해서 ACK을 보낸다.
※ SEQ번호는 응답받은 ACK번호와 같아야 한다.
3. SEQ:1401, 100바이트를 보냈는데 손실되었다. 보내는 동시에 타이머를 작동.
손실되었으므로 응답이 없다. 상대방이 못받았다고 생각하므로
4. SEQ:1401, 100바이트를 다시 보낸다.
5. ACK을 보낸다.
3. 연결 종료 단계
클라이언트 혹은 서버가 close(closesocket) 함수 호출 시 진행
four-way handshaking
1. FIN(A->B) : 종료 요청의 메세지를 담은 패킷을 보낸다. FINish
2. ACK(B->A) : 단순히 패킷을 잘 받았다는 신호만 보낸다. 아직 종료할 상황이라는 뜻은 아니다.
3. FIN(B->A) : 종료해도 좋다는 의미의 FINish를 보낸다.
4. ACK(A->B) : 최종적인 수신 응답 메세지 ACK을 전송한다.