
Socket과 TCP/UDP 소켓의 기본 구조를 알아봅니다.
소켓(Socket)은 네트워크를 통한 입출력을 위해 사용자에게 필요한 수단을 제공하는 응용 프로토콜 인터페이스입니다.


| 요소 | 설명 |
|---|---|
| 프로토콜(Protocol) | 4계층에서 어떤 프로토콜을 사용하는지 (TCP/UDP) |
| 소스 IP 주소 | 데이터를 보내는 호스트의 IP |
| 소스 포트 번호 | 데이터를 보내는 프로세스 식별자 |
| 목적지 IP 주소 | 데이터를 받는 호스트의 IP |
| 목적지 포트 번호 | 데이터를 받는 프로세스 식별자 |
💡 포트 번호는 네트워크에서 프로세스들의 식별자라고 생각하면 됩니다.
호스트 내에 실행되고 있는 프로세스(Process)를 구분 짓기 위한 16비트의 논리적 할당입니다.

TCP 또는 UDP에서 IANA에 의해 할당된 0번 ~ 1023번까지의 포트입니다.
| 포트 번호 | 서비스 |
|---|---|
| 20, 21 | FTP |
| 22 | SSH |
| 23 | Telnet |
| 25 | SMTP |
| 53 | DNS |
| 80 | HTTP |
| 443 | HTTPS |

| 방식 | 설명 |
|---|---|
| Big Endian | 상위 바이트의 값을 작은 번지수에 저장 |
| Little Endian | 상위 바이트의 값을 큰 번지수에 저장 |
⚠️ 네트워크 통신 시 바이트 순서 변환이 필요합니다!

💡 Socket의 역할: Application(5계층)에서 TCP로 보내달라고 Transport(4계층)에게 요청하기
TCP Client가 n개 들어오면 Socket은 n+1개 존재합니다. (listen 소켓 1개 + 통신용 n개)
[Client] [Server]
│ │
│ socket() - 소켓 생성 │ socket() - 소켓 생성
│ │ bind() - IP/Port 바인딩
│ │ listen() - 연결 대기
│ │
│ ─────── connect() ───────────────▶ │ accept() - 연결 수락
│ ◀───── 3-way handshake ──────────▶ │ (새 소켓 생성)
│ │
│ ◀────── read/write ───────────────▶ │ (데이터 송수신)
│ │
│ close() │ close() (통신 소켓)
│ │ close() (listen 소켓)


socket(): 소켓 생성address: 통신을 요청할 상대방(서버)의 주소 설정socket(): 소켓 생성address: 자신의 IP 주소와 Port 번호 설정 (누가 들어올지 모르니 내 정보만 설정)bind(): IP와 Port 번호를 OS에게 알려주는 절차 ⭐ 매우 중요!listen(): Client의 접속 요청을 대기하는 상태connect(): Client가 listen 중인 Server에게 연결 요청accept(): Server가 새로운 소켓을 만들어 Client와 데이터 송수신 준비read()/write(): 양측 모두 데이터 송수신close(): Client가 먼저 소켓 종료 → Server도 통신 소켓 종료close(): listen 소켓까지 종료TCP 연결 수립 과정 (connect ~ accept 구간)
Client Server
│ │
│ ──── SYN ─────────────▶ │
│ ◀─── SYN + ACK ──────── │
│ ──── ACK ─────────────▶ │
│ │
│ 연결 수립 완료 │


// 1. 사용자 입력을 위한 BufferedReader 생성
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
// 2. 서버 연결 (hostname: 서버 IP, 6789: 포트 번호)
Socket clientSocket = new Socket("hostname", 6789);
// 3. 서버로 데이터 전송
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
String sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
// 4. 서버로부터 응답 수신
BufferedReader inFromServer = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String modifiedSentence = inFromServer.readLine();
// 5. 소켓 종료
clientSocket.close();
// 1. ServerSocket 생성 및 바인딩 (포트 6789)
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
// 2. 클라이언트 연결 대기 및 수락 (새 소켓 생성)
Socket connectionSocket = welcomeSocket.accept();
// 3. 클라이언트로부터 데이터 수신
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));
String clientSentence = inFromClient.readLine();
// 4. 대문자 변환 후 클라이언트에게 전송
DataOutputStream outToClient = new DataOutputStream(
connectionSocket.getOutputStream());
String capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
}

| 특성 | 설명 |
|---|---|
| 순서 보장 ❌ | 패킷은 전달된 순서대로 수신되지 않음 |
| 신뢰성 ❌ | 에러 복구를 하지 않음 |
| 크기 제한 ⭕ | 데이터그램 패킷의 크기가 고정 |
| Pipeline ❌ | TCP와 다르게 파이프라인 불가능 |
| 구분 | TCP | UDP |
|---|---|---|
| 연결 | 연결 지향 (3-way handshake) | 비연결 |
| 신뢰성 | 보장 | 미보장 |
| 순서 | 보장 | 미보장 |
| 속도 | 상대적으로 느림 | 빠름 |
| 용도 | 웹, 이메일, 파일 전송 | 스트리밍, 게임, DNS |
[Client] [Server]
│ │
│ socket() - 소켓 생성 │ socket() - 소켓 생성
│ │ bind() - IP/Port 바인딩
│ │
│ ─────── sendto() ─────────────────▶ │ recvfrom()
│ ◀────── recvfrom() ──────────────── │ sendto()
│ │
│ close() │ close()
💡 UDP는 connect(), accept()가 없습니다! 바로 데이터를 보내고 받습니다.


// 1. DatagramSocket 생성
DatagramSocket clientSocket = new DatagramSocket();
// 2. 서버 주소 설정
InetAddress IPAddress = InetAddress.getByName("hostname");
// 3. 전송할 데이터 준비
byte[] sendData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
// 4. 패킷 생성 및 전송 (데이터, 길이, IP, 포트)
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
// 5. 응답 수신
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
// 6. 소켓 종료
clientSocket.close();
// 1. DatagramSocket 생성 및 포트 바인딩
DatagramSocket serverSocket = new DatagramSocket(9876);
// 2. 수신 버퍼 준비 (경계 단위 고정)
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
// 3. 데이터 수신 대기
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket); // 연결 없이 바로 receive
String sentence = new String(receivePacket.getData());
// 4. 클라이언트 정보 추출
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
// 5. 대문자 변환 후 응답 전송
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
| 구분 | TCP (SOCK_STREAM) | UDP (SOCK_DGRAM) |
|---|---|---|
| 연결 방식 | 연결 지향 | 비연결 |
| 데이터 단위 | 스트림 (경계 없음) | 데이터그램 (경계 있음) |
| 순서 보장 | ⭕ | ❌ |
| 신뢰성 | ⭕ | ❌ |
| 서버 소켓 수 | n+1개 (Client n개 기준) | 1개 |
| 주요 메서드 | connect, accept, listen | sendto, recvfrom |