💡 해당 글은 『자바의 신 3판』을 복습하며 도서의 내용과 본인의 주관적인 생각을 정리한 글입니다.
☁️ 내용정리
네트워크 프로그래밍
애플리케이션 계층은 OSI 7 layer의 최상단에 위치한다. 애플리케이션 계층의 대표적인 HTTP
, FTP
, Telnet
들은 모두 TCP
통신을 한다. 우리가 자바로 TCP 통신을 하고싶다면 자바에서 제공하는 API를 사용하면 된다.
TCP는 3-Way-hashShake를 통해 상대방이 데이터를 받았는지를 확실히 보장할 수 있다.
전송 제어 프로토콜(Transmission Control Protocol, TCP)은 인터넷 프로토콜 스위트(IP)의 핵심 프로토콜 중 하나로, IP와 함께 TCP/IP라는 명칭으로도 널리 불린다.
- 위키피디아
TCP는 안정성을 제공하지만 연결의 수행하기 위한 3-Way-handshake
과 연결을 해제하기 위한 4-Way-Handshake
를 수행하며 발생하는 오버헤드가 존재한다.
TCP의 안정성을 필요로 하지 않는 애플리케이션의 경우 일반적으로 TCP 대신 UDP를 사용한다. UDP는 전달 확인 및 순차 보장 기능이 없는 대신 오버헤드가 작고 지연시간이 짧다는 장점이 있다.
포트에 대해 알아보자. 일반적인 웹 애플리케이션에는 80이라는 번호의 포트를 사용한다.(정해져 있음)
만약 99번 포트를 쓰고 싶다면 99번 포트 사용을 지정하고 URL 뒤에 :99 를 붙어여 한다. 기본적으로 80이 붙어있다. 웹으로 SSL이라는 안전한 통신을 하려면 443포트를 사용하게 된다.
소캣 통신을 위한 Socket 클래스
java.net
패키지에는 네트워크 통신을 위한 많은 클래스들이 선언되어 있다.
소켓(Socket)은 TCP/IP 기반 네트워크 통신에서 데이터 송수신의 마지막 접점을 말한다. 소켓통신은 이러한 소켓을 통해 서버-클라이언트간 데이터를 주고받는 양방향 연결 지향성 통신을 말한다. 소켓통신은 보통 지속적으로 연결을 유지하면서 실시간으로 데이터를 주고받아야 하는 경우에는 사용된다.
소켓은 클라이언트 소켓과 서버 소켓으로 구분되며, 소켓간 통신을 위해서는 네트워크상에서 클라이언트와 서버에 해당되는 컴퓨터를 식별하기 위한IP주소와 해당 컴퓨터내에서 현재 통신에 사용되는 응용프로그램을 식별하기 위한 포트번호가 사용된다.
Socket 클래스는 데이터를 보내는 쪽에서 객체를 생성하여 사용한다. 데이터를 받는 쪽(ServerSocket
)에서 클라이언트 요청을 받으면, 요청에 대한 Socket
객체를 생성하여 데이터를 처리한다.
TCP는 스트림기반 통신을 한다.
먼저 연결을 대기하는 소켓 서버부터 작성한다.
public class SocketServer {
public static void main(String[] args) {
SocketServer socketServer = new SocketServer();
socketServer.startServer();
}
public void startServer() {
try (ServerSocket server = new ServerSocket(9999)) { // 9999포트를 가지는 서버 소켓 생성
while (true) {
System.out.println("Server: Waiting for request.");
Socket client = server.accept(); // 다른 원격 호출을 대기하는 상태, 만약 연결이 완료되면 Socket 객체를 리턴
// Socket을 읽기 위한 스트림 생성
try (BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()))) {
String data;
StringBuilder receivedData = new StringBuilder();
while ((data = reader.readLine()) != null) {
receivedData.append(data);
}
System.out.println("Server: ReceivedData= " + receivedData);
if ("EXIT".contentEquals(receivedData)) {
System.out.println("Stop Socket Server");
break;
}
System.out.println("--------------------");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
통신을 위한 연결이 생성되면 소켓의 스트림을 얻어와 데이터를 출력하고 데이터가 EXIT 문자열인 경우 서버를 종료하도록 코드를 작성하였다. 이제 프로그램을 실행하면 해당 프로세스는 통신을 위한 연결을 기다린다.
데이터를 쓰고 전달하는 클라이언트단 코드를 작성해보자. 데이터를 3번 전송하고 EXIT 문자열을 전송할 것이다.
public class SocketClient {
public static void main(String[] args) {
SocketClient socketClient = new SocketClient();
socketClient.sendSocket();
}
private void sendSocket() {
for (int loop = 0; loop < 3; loop++) {
this.sendSockData("Send Data " + loop + " at " + new Date());
}
this.sendSockData("EXIT");
}
private void sendSockData(String message) {
try (Socket socket = new Socket(InetAddress.getLocalHost(), 9999)) {
System.out.println("Client: Connect status=" + socket.isConnected());
Thread.sleep(1000);
try (BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream())) {
outputStream.write(message.getBytes());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
서버 프로그램을 실행시킨 상태에서 클라이언트단 프로그램을 실행하면 결과는 아래와 같다.
// Client
Client: Connect status=true
Client: Connect status=true
Client: Connect status=true
Client: Connect status=true
//Server
Server: Waiting for request.
Server: ReceivedData= Send Data 0 at Thu Jan 11 09:56:10 KST 2024
--------------------
Server: Waiting for request.
Server: ReceivedData= Send Data 1 at Thu Jan 11 09:56:11 KST 2024
--------------------
Server: Waiting for request.
Server: ReceivedData= Send Data 2 at Thu Jan 11 09:56:12 KST 2024
--------------------
Server: Waiting for request.
Server: ReceivedData= EXIT
Stop Socket Server
UDP와 Datagram 클래스
UDP
는 TCP와 달리 데이터가 제대로 전달되었다는 보장을 하지 않는다. 따라서 UDP관련 프로그램은 데이터의 유실이 있어도 문재가 없을 때만 사용하는 것이 좋다.
UDP도 데이터를 주고 받기 위한 클래스가 필요하다. UDP는 TCP와는 다르게 클래스 하나가 보내는 역할과 받는 역할을 모두 수행할 수 있는데, DatagramSocket
이라는 클래스를 사용한다.
또 TCP는 스트림기반 통신을 하는 반면, UDP는 DatagramPacket
이라는 클래스를 사용한다.
public class DatagramServer {
public static void main(String[] args) {
DatagramServer server = new DatagramServer();
server.startServer();
}
private void startServer() {
try (DatagramSocket server = new DatagramSocket(9999)) {
int bufferLength = 256;
byte[] buffer = new byte[bufferLength];
DatagramPacket packet = new DatagramPacket(buffer, bufferLength);
while (true) {
System.out.println("Server: Waiting for request.");
server.receive(packet);
int dataLength = packet.getLength();
System.out.println("Server: Received. Data Length = " + dataLength);
String data = new String(packet.getData(), 0, dataLength);
System.out.println("Server: Received Data = " + data);
if ("EXIT".equalsIgnoreCase(data)) {
System.out.println("Stop DatagramServer");
break;
}
System.out.println("--------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class DatagramClient {
public static void main(String[] args) {
DatagramClient client = new DatagramClient();
client.sendDatagram();
}
private void sendDatagram() {
for (int loop = 0; loop < 3; loop++) {
this.sendDatagramData("Send Data " + loop + " at " + new Date());
}
this.sendDatagramData("EXIT");
}
private void sendDatagramData(String message) {
try (DatagramSocket client = new DatagramSocket();) {
InetAddress address = InetAddress.getByName("127.0.0.1");
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, address, 9999);
client.send(packet);
System.out.println("Client: sent Data");
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
결과는 ServerSocket, Socket 클래스를 사용한 TCP 통신과 동일하다. 다른점이 있다면, TCP와는 다르게 UDP는 서버의 존재를 모른 상태로 데이터 전송을 시도해도 아무런 오류를 발생시키지 않는다는 점이다.
☁️ 질문
- 자바에서 TCP 통신 기능을 구현하려면 어떤 클래스를 사용해야 하고, 어떤 자원을 기반으로 통신하는가?
- 데이터 송신 측은 Socket, 데이터 수신 측은 ServerSocket 클래스를 사용하고, 스트림 기반으로 통신한다.
- 자바에서 UDP 통신 기능을 구현하려면 어떤 클래스를 사용해야 하고, 어떤 자원을 기반으로 통신하는가?
- 데이터 송수신 측 모두 DatagramSocket 클래스를 사용하고 DatagramPacket 기반으로 통신한다.
'JAVA > 자바의 신' 카테고리의 다른 글
27장. Serializable과 NIO도 살펴 봅시다. (1) | 2024.01.11 |
---|---|
26장. 파일에 있는 것을 읽고 쓰려면 아이오를 알아야죠 (0) | 2024.01.10 |
25장. 스레드는 개발자라면 알아두는 것이 좋아요 (1) | 2024.01.10 |
23, 24장. 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - Set, Queue, Map (2) | 2024.01.10 |
22장. 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - List (1) | 2024.01.10 |