소켓 프로그래밍이란? 소켓을 이용한 통신 프로그래밍을 뜻하는데, 소켓이란 프로세스 간의 통신에 사용되는 양쪽 끝단(endpoint)를 의미한다. 서로 멀리 떨어진 두 사람이 통신하기 위해서 전화기가 필요한 것 처럼, 프로세스간의 통신을 위해서는 그 무언가가 필요하고 그것이 바로 소켓이다.
자바에서는 java.net패키지를 통해 소켓 프로그래밍을 지원하는데, 소켓통신에 사용되는 프로토콜에 따라 다른 종류의 소켓을 구현하여 제공한다.
TCP와 UDP를 이용해 소켓 프로그래밍에 대해 공부해 보자.
TCP/IP 프로토콜은 이기종 시스템간의 통신을 위한 표준 프로토콜로 프로토콜의 집합이다.
TCP와 UDP 둘 모두 TCP/IP 프로토콜에 포함돼 있으며 OSI7계층의 전송계층에 해당하는 프로토콜이다.
TCP와 UDP는 각 방식에 따른 장단점이 있고, 전송 방식도 다르다. 어플리케이션의 특징에 따라 적절한 프로토콜을 선택하면 된다.
저자는 TCP를 이용한 통신은 전화에, UDP를 이용한 통신은 소포에 비유했는데, TCP는 데이터를 전송하기 전에 먼저 상대편과 연결을 한 후에 데이터를 전송하며 잘 전송됐는지 확인하며, 전송에 실패했다면 해당 데이터를 재전송 하기 때문에 신뢰 있는 데이터의 전송이 요구되는 통신에 적합하다. 예를 들면 파일을 주고 받는데 적합하다.
반면에 UDP는 상대편과 연결하지 않고 데이터를 전송하며, 데이터를 전송하지만 데이터가 바르게 수신됐는지는 알 수 없기 때문에 데이터가 전송됐는지 확인할 길이 없다.
또한 데이터를 순서대로 보낸다는 보장도 할 수 없다.
하지만 이런 확인 과정이 없어 TCP보다 빠른 전송이 가능하다.
UDP는 게임이나 동영상의 데이터를 전송하는 경우와 같이, 데이터가 중간에 조금씩 손실되어 좀 끊기더라도 빠른 전송이 필요할 때 적합하다. 이때 전송 순서가 바뀌어 늦게 도착한 데이터는 무시하면 그만이다.
TCP는 1:1 통신이다. 먼저 서버 프로그램이 실행되어 클라이언트의 요청을 받을 준비가 끝나야 한다. 서버 프로그램과 클라이언트 프로그램간의 통신과정을 단계별로 알아보자
서버 프로그램에서는 서버 소켓을 사용해서 서버 컴퓨터의 특정 포트에서 클라이언트의 연결 요청을 처리할 준비를 한다.
클라이언트 프로그램은 접속할 서버의 IP주소와 포트 정보를 가지고 소켓을 생성해서 서버에 연결을 요청한다.
서버소켓은 클라이언트의 연결요청을 받으면, 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과 연결되도록 한다.
이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버 소켓과 관계없이 1:1 통신을 한다.
서버 소켓은 포트와 결합 되어 포트를 통해 원격 사용자의 연결요청을 기다리다가 연결 요청이 올 때마다 새로운 소켓을 생성하여 상대편 소켓과 통신할 수 있도록 연결한다. 여기까지가 서버소켓의 역할이며 실제적인 데이터 통신은 서버소켓과 관계없이 소켓과 소켓 간에 이루어진다.
포트(port)는 호스트(컴퓨터)가 외부와 통신하기 위한 통로로 하나의 호스트가 65536개의 포트를 가지고 있으며 포트는 번호로 구별된다. 포트의 번호는 보통 1023번 이하의 포트에서 FTP나 Telnet과 같은 기존의 다른 통신 프로그램들에 의해서 사용되는 경우가 많기에 1023번 이상의 번호 중에서 사용하지 않는 포트를 골라 사용해야 한다.
서버소켓은 소켓간의 연결만 처리하고 실제 데이터는 소켓들끼리 서로 주고받는다. 소켓들이 데이터를 주고받는 연결통로는 바로 I/O Stream이다.
각각의 소켓들은 두 개의 스트림, Input과 Output스트림을 갖는데 이 스트림들은 여결된 상대편 소켓의 Input-Output , Output-Input으로 연결된다.
자바에서는 TCP를 이용한 소켓프로그래밍을 위해 Socket과 ServerSocket클래스를 제공하며 다음과 같은 특징을 갖고 있다.
Socket
프로세스간의 통신을 담당하며, InputStream과 OutputStream을 가지고 있다. 이 두 스트림을 통해 프로세스간의 통신이 이루어진다
ServerSocket
포트와 연결되어 외부의 연결요청을 기다리다 연결요청이 들어오면, Socket을 생성해서 소켓과 소켓간의 통신이 이루어지도록 한다. 한 포트에 하나의 ServerSocket만 연결할 수 있다.(프로토콜이 다르면 같은 포트를 다른 서버소켓과 공유 가능하다.)
TCP에서는 Socket과 ServerSocket을 사용하나 UDP에서는 DatagramSocket과 DatagramPacket을 사용한다.
앞서 살펴본 바와 같이 UDP는 연결지향적인 프로토콜이 아니라 ServerSocket이 필요하지 않다. UDP통신에서는 사용하는 소켓이 DatagramSocket이며 데이터를 DatagramPacket에 담아 전송한다.
DatagramPacket은 헤더와 데이터로 구성돼 있으며, 헤더에는 DatagramPacket을 수신할 호스트의 정보(호스트의 주소와 포트)가 저장돼 있다. 소포(packet)에 수신할 상대편의 주소를 적어 보내는 것과 같다고 이해하자.
그래서 DatagramPacket을 전송하면 DatagramPacket에 지정된 주소의 DatagramSocket에 도착한다.