TCP
서버 측
1. ServerSocket
TCP 서버 프로그램을 개발하려면 우선 ServerSocket 객체를 생성해야 한다.
ServerSocket은 데이터 송수신용 소켓이 아닌 연결을 대기하는 소켓이다.
ServerSocet객체를 생성할 때는 포트 번호를 넘겨줘야 한다.
int portNum = 5000;
ServerSocket serverSocket = new ServerSocket(portNum);
다음과 같이 bind()메서드에 InetSocketAddress 객체를 포트번호와 함께 넘겨주면 된다.
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(5000));
만약 서버 컴퓨터에 여러 개의 IP가 할당되어 있는 경우, 특정 IP에서만 서비스하고 싶다면 InetSocketAddress에 해당 IP를 주면 된다.
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("xxx.xxx.xxx.xxx", 5000));
2. Socket
ServerSocket을 통해 받은 연결을 수락하기 위한 별도의 소켓이 필요하다.
Socket socket = serverSocket.accept();
3. 연결된 클라이언트 측 정보
리턴된 Socket을 통해 얻어올 수 있다.
getRemoteSocketAddress()를 사용하면 된다.
InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("클라이언트 IP: " + isa.getHostString() + "클라이언트 포트: " + isa.getAddress());
4. 서버 종료하기
서버를 종료해야지 해당 port번호를 재사용할 수 있다.
clost()를 통해 서버를 종료한다.
serverSocket.close();
클라이언트 측
1. Socket
클라이언트가 서버에 연결을 요청하려면 Socket 객체를 생성할 때 생성자의 매개변수로 서버의 IP 주소와 Port번호를 제공하면 된다.
Socket socket = new Socket("서버 IP", 서버 포트번호)
만약 IP주소 대신 도메인 이름을 사용하고 싶다면, DNS에서 IP 주소를 검색할 수 있도록 생성자의 매개변수로 InetAddress를 제공해야 한다.
Socket socket = new Socket(InetSocketAddress.getByName("도메인 이름"), 서버 포트번호);
만약 Socket 객체 생성 시점이 아니라 나중에 연결하고 싶다면 connect()메서드를 사용하면 된다.
Socket socket = new Socket();
socket.connect(InetSocketAddress.getByName("도메인 이름"), 서버 포트번호);
데이터 주고받기
TCP는 데이터의 신뢰성을 보장하는 전송 방법이기 때문에 입출력 스트림을 통해 데이터를 주고받는다.
데이터 쓰기
socket.getOutputStream()을 통해 OutputStream을 받아온다.
받아온 OutputStream은 다양한 하위 클래스로 변환해서 사용할 수 있다.
여기선 BufferedWriter를 사용하겠다.
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
write() 메서드를 사용해서 보내고 싶은 데이터를 넣으면 된다.
String data = "보낼 데이터";
bw.write(data + "\n");
- BufferedReader에서는 readLine()을 통해 줄 단위로 데이터를 읽기 때문에 개행 문자를 추가했다.
데이터 읽기
socket.getInputStream()을 통해 InputStream을 받아온다.
받아온 InputStream은 다양한 하위 클래스로 변환해서 사용할 수 있다.
여기선 BufferedReader를 사용하겠다.
BufferedReader br = new BufferedReader(new InputStreamWriter(socket.getInputStream()));
readLine() 메서드를 사용해서 데이터를 읽어오면 된다.
String data = br.readLine();
UDP
UDP에서는 DatagramSocket을 통해 서버와 클라이언트를 연결하고 DatagramPacket 객체를 주고 받는다.
서버 측
1. DatagramSocket
UDP 서버를 위한 DatagramSocket 객체를 생성할 때 바인딩할 포트 번호를 생성자의 매개변수로 넘겨줘야 한다.
DatagramSocket socket = new DatagramSocket(포트 번호);
2. 데이터 수신 대기
UDP 서버는 클라이언트가 보낸 DatagramPacket을 항상 받을 준비를 해야 한다.
이때 receive() 메서드를 사용한다.
receive()메서드는 데이터를 수신할 때까지 블로킹되고 데이터가 수신되면 매개 변수로 주어진 DatagramPacket에 저장한다.
DatagramPacket receivePacket= new DatagramPacket(new byte[1024], 1024);
System.out.println("데이터 수신 대기중");
datagramSocket.receive(receivePacket); // 기다림
3. 수신한 데이터 읽기
getData()를 통해 데이터를 바이트 배열 행태로 바꿔올 수 있다.
byte[] bytes = receivePacket.getData();
만약 읽어올 데이터가 문자열이라면 다음과 같이 String 생성자를 통해 얻어올 수 있다.
String data = new String(bytes, 0, bytes.length);
4. 클라이언트에게 데이터 보내기
String data = "보낼 내용";
byte[] byteMsg = msg.getBytes(StandardCharsets.UTF_8);
DatagramPacket sendPacket = new DatagramPacket(byteMsg, byteMsg.length,
receivePacket.getSocketAddress());
- getSocketAddress()를 통해 수신한 클라인트의 정보를 알 수 있다.
send()메서드를 통해 보내면 된다.
sendSocket.send(sendPacket);
5. 서버 종료
sendSocket.close();
클라이언트 측
1. DatagramSocket
UDP 클라이언트의 DatagramSocket 객체 Port번호는 자동으로 부여되기 때문에 따로 지정할 필요가 없다.
DatagramSocket socket = new DatagramSocket();
2. 서버에 데이터 보내기
String data = "보낼 내용";
byte[] byteMsg = msg.getBytes(StandardCharsets.UTF_8);
DatagramPacket sendPacket = new DatagramPacket(byteMsg, byteMsg.length,
new InetSocketAddress("서버 IP", 서버 포트번호));
- 만약 서버에게 받은 패킷이 있다면 getSocketAddress()를 사용해도 된다.
'Java' 카테고리의 다른 글
[Java] 스레드(Thread) (0) | 2024.07.27 |
---|---|
[Java] 해시기반 컬렉션의 동등성 비교(hashCode() 메서드의 필요성) (0) | 2024.07.25 |
[Java] Stream API (0) | 2024.07.25 |
[Java] 람다식의 이해 (0) | 2024.07.25 |
[Java] HashMap - value값을 기준으로 정렬 (0) | 2024.07.23 |