[사용자]
↓
[HTTP 등 응용 계층]
↓
[TCP/UDP 전송 계층]
↓
[IP 네트워크 계층]
↓
[하드웨어/물리 계층 (WiFi, LAN 등)]
즉, 사용자가 웹 요청을 보내면:
1. HTTP가 요청을 만듦
2. 그 요청을 TCP가 나눠서 전달하고
3. IP가 어디로 보낼지 결정하고
4. 마지막으로 실제 랜선/와이파이를 통해 전송됨
소켓은 네트워크 통신을 위한 창구 (전화기)
데이터를 주고받을 수 있는 프로세스 간 통신의 끝점
socket(); // 소켓 생성
bind(); // IP, 포트에 바인딩
listen(); // 연결 대기 (backlog: 동시에 대기 가능한 수)
accept(); // 클라이언트 연결 수락
read()/write(); // 데이터 송수신
socket(); // 소켓 생성
connect(); // 서버 IP, 포트로 연결 요청
read()/write(); // 데이터 송수신
소켓을 닫아서 더 이상 네트워크 통신을 하지 않도록 하는 작업
close(sockfd);
네트워크 통신은 시스템 자원(파일 디스크립터)을 사용함
close()를 호출하지 않으면 자원이 해제되지 않아 자원 누수(resource leak) 발생
서버나 클라이언트가 통신을 마치고 나면 반드시 닫아줘야 함
클라이언트- 통신을 마친 후 close()를 호출하면, 서버에게 “나 이제 안 쓸게”라고 알려줌. 연결 종료 요청(FIN) 전송.
서버- 클라이언트와의 대화를 마친 후, 자신이 생성한 대화용 소켓(accept가 반환한 소켓)을 close()해야 자원이 해제됨.
서버에서 주의할 점
서버는 listen()용 대기 소켓과 accept()가 반환한 대화용 소켓이 따로 있음
int listenfd = socket(...); // 대기용
bind(listenfd, ...);
listen(listenfd, ...);
int connfd = accept(listenfd, ...); // 대화용
// 클라이언트와 통신
read(connfd, ...);
write(connfd, ...);
close(connfd); // 대화용 소켓 닫기 (반드시 필요)
listenfd는 여러 클라이언트를 받기 위한 것이므로, 보통 서버 종료할 때만 close(listenfd)를 호출
양쪽 모두 close()를 호출해야 TCP 연결이 완전히 종료
• 클라이언트는 하나의 소켓을 닫고 끝
• 서버는 클라이언트별로 생성된 소켓(connfd)를 매번 닫아야 자원이 안 쌓임