Search

240607_1008_TCP(Transmission Control Protocol)프로토콜의 3-way handshake와 4-way handshake

TCP(Transmission Control Protocol)는 신뢰성 있는 통신을 제공하기 위해 3-way handshake와 4-way handshake를 사용합니다. 이 과정은 각각 연결을 설정하고 종료하는 절차를 의미합니다.

3-Way Handshake (연결 설정)

3-way handshake는 TCP 연결을 설정하기 위한 세 가지 단계로 구성됩니다.
1.
SYN (Synchronize Sequence Numbers)
클라이언트는 서버와의 연결을 시작하기 위해 초기 순서 번호(Sequence Number)를 포함한 SYN 패킷을 서버로 보냅니다.
이 패킷에는 클라이언트의 초기 순서 번호(ISN: Initial Sequence Number)가 포함됩니다.
클라이언트 -> 서버: SYN, Seq = x
Rust
복사
2.
SYN-ACK (Synchronize Acknowledgment)
서버는 클라이언트의 SYN 패킷을 수신하고 이를 확인(ACK: Acknowledgment)합니다. 동시에 서버도 자신의 초기 순서 번호를 포함한 SYN 패킷을 클라이언트로 보냅니다.
이 패킷에는 클라이언트의 ISN에 대한 확인 응답(ACK = x+1)과 서버의 ISN(Seq = y)이 포함됩니다.
서버 -> 클라이언트: SYN, ACK, Seq = y, Ack = x+1
Rust
복사
3.
ACK (Acknowledgment)
클라이언트는 서버의 SYN-ACK 패킷을 수신하고 이를 확인합니다. 그런 다음, 연결이 설정되었음을 서버에게 알리기 위해 자신의 순서 번호를 증가시킨 ACK 패킷을 서버로 보냅니다.
이 패킷에는 서버의 ISN에 대한 확인 응답(ACK = y+1)이 포함됩니다.
클라이언트 -> 서버: ACK, Seq = x+1, Ack = y+1
Rust
복사
이로써 양쪽 모두 연결이 설정되었음을 인지하게 되고, 데이터 전송이 시작될 수 있습니다.

4-Way Handshake (연결 종료)

4-way handshake는 TCP 연결을 종료하기 위한 네 가지 단계로 구성됩니다.
1.
FIN (Finish)
연결을 종료하고자 하는 쪽(주로 클라이언트)은 연결 종료 요청을 나타내는 FIN 패킷을 상대방에게 보냅니다.
이 패킷은 클라이언트의 순서 번호(Seq = u)를 포함합니다.
클라이언트 -> 서버: FIN, Seq = u
Rust
복사
2.
ACK (Acknowledgment)
서버는 클라이언트의 FIN 패킷을 수신하고 이를 확인하는 ACK 패킷을 보냅니다.
이 패킷은 클라이언트의 순서 번호에 대한 확인 응답(ACK = u+1)을 포함합니다.
서버 -> 클라이언트: ACK, Seq = v, Ack = u+1
Rust
복사
3.
FIN (Finish)
서버는 자신의 데이터 전송이 완료되면 연결 종료 요청을 나타내는 FIN 패킷을 클라이언트로 보냅니다.
이 패킷은 서버의 순서 번호(Seq = w)를 포함합니다.
서버 -> 클라이언트: FIN, Seq = w
Rust
복사
4.
ACK (Acknowledgment)
클라이언트는 서버의 FIN 패킷을 수신하고 이를 확인하는 ACK 패킷을 보냅니다.
이 패킷은 서버의 순서 번호에 대한 확인 응답(ACK = w+1)을 포함합니다.
클라이언트 -> 서버: ACK, Seq = u+1, Ack = w+1
Rust
복사
이로써 양쪽 모두 연결이 종료되었음을 인지하게 됩니다. FIN과 ACK 패킷의 순서는 반드시 이 순서를 따르며, 각 단계는 이전 단계의 패킷에 대한 확인 응답을 포함합니다.
TCP의 3-way handshake와 4-way handshake는 신뢰성 있는 연결 설정 및 종료를 보장하여 데이터 전송의 신뢰성을 높입니다.

Js 코드 시뮬레이션

TCP의 3-way handshake와 4-way handshake 과정을 JavaScript 코드로 시뮬레이션할 수 있습니다.
클라이언트와 서버 간의 메시지 교환을 시뮬레이션하는 간단한 예제를 통해 설명하겠습니다.

3-Way Handshake (연결 설정)

class TCPConnection { constructor() { this.clientSeq = 0; this.serverSeq = 0; } // 클라이언트가 서버에 연결을 요청합니다. clientSendSYN() { this.clientSeq = Math.floor(Math.random() * 1000); console.log(`Client: Sending SYN, Seq = ${this.clientSeq}`); this.serverReceiveSYN(this.clientSeq); } // 서버가 SYN을 수신하고 SYN-ACK를 응답합니다. serverReceiveSYN(clientSeq) { this.serverSeq = Math.floor(Math.random() * 1000); console.log(`Server: Received SYN, Seq = ${clientSeq}`); console.log(`Server: Sending SYN-ACK, Seq = ${this.serverSeq}, Ack = ${clientSeq + 1}`); this.clientReceiveSYNACK(this.serverSeq, clientSeq + 1); } // 클라이언트가 SYN-ACK를 수신하고 ACK를 응답합니다. clientReceiveSYNACK(serverSeq, clientAck) { console.log(`Client: Received SYN-ACK, Seq = ${serverSeq}, Ack = ${clientAck}`); console.log(`Client: Sending ACK, Seq = ${clientAck}, Ack = ${serverSeq + 1}`); this.serverReceiveACK(serverSeq + 1); } // 서버가 최종 ACK를 수신합니다. serverReceiveACK(expectedAck) { console.log(`Server: Received ACK, Ack = ${expectedAck}`); console.log('Connection established!'); } } const connection = new TCPConnection(); connection.clientSendSYN();
JavaScript
복사

4-Way Handshake (연결 종료)

class TCPConnection { constructor() { this.clientSeq = 0; this.serverSeq = 0; } // 클라이언트가 연결 종료를 요청합니다. clientSendFIN() { console.log(`Client: Sending FIN, Seq = ${this.clientSeq}`); this.serverReceiveFIN(this.clientSeq); } // 서버가 FIN을 수신하고 ACK를 응답합니다. serverReceiveFIN(clientSeq) { console.log(`Server: Received FIN, Seq = ${clientSeq}`); console.log(`Server: Sending ACK, Seq = ${this.serverSeq}, Ack = ${clientSeq + 1}`); this.clientReceiveACK(clientSeq + 1); this.serverSendFIN(); } // 클라이언트가 ACK를 수신합니다. clientReceiveACK(ack) { console.log(`Client: Received ACK, Ack = ${ack}`); } // 서버가 연결 종료를 요청합니다. serverSendFIN() { console.log(`Server: Sending FIN, Seq = ${this.serverSeq}`); this.clientReceiveFIN(this.serverSeq); } // 클라이언트가 FIN을 수신하고 ACK를 응답합니다. clientReceiveFIN(serverSeq) { console.log(`Client: Received FIN, Seq = ${serverSeq}`); console.log(`Client: Sending ACK, Seq = ${this.clientSeq + 1}, Ack = ${serverSeq + 1}`); this.serverReceiveACK(serverSeq + 1); } // 서버가 최종 ACK를 수신합니다. serverReceiveACK(ack) { console.log(`Server: Received ACK, Ack = ${ack}`); console.log('Connection closed!'); } } const connection = new TCPConnection(); connection.clientSendFIN();
JavaScript
복사
위 코드는 TCP 3-way handshake와 4-way handshake 과정을 시뮬레이션합니다. 각각의 메시지 교환을 통해 연결이 설정되고 종료되는 과정을 확인할 수 있습니다.

안녕하세요

한국전자기술연구원 김영광입니다.
관련 기술 문의와 R&D 공동 연구 사업 관련 문의는 “glory@keti.re.kr”로 연락 부탁드립니다.

Hello

I'm Yeonggwang Kim from the Korea Electronics Research Institute.
For technical and business inquiries, please contact me at “glory@keti.re.kr”