•
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”