Java를 이용한 전이중 통신

Jan 10, 2024
Java를 이용한 전이중 통신
 
전이중 통신은 채팅 처럼 양방향에서 동시에 통신이 가능한 방식이다.
자바를 통해 채팅이 가능한 코드를 만들어보자.
 
소켓과 버퍼에 관한 내용은 아래의 블로그에서 확인할 수 있다.
 

1. 클라이언트 → 서버 일방적 채팅 보내기

 
클라이언트는 BufferedWriter 를 만들고, 서버는 BufferedReader 를 만든다. 자바는 간소화를 위해
BufferedWriter 는 PrintWriter 로 대체해서 사용할 수 있다. 반복된 채탱을 보내기 위해 while 문을 사용한다.
 
public class Client { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 5000); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); Scanner sc = new Scanner(System.in); while (true) { String msg = sc.nextLine(); pw.println(msg); } } catch (IOException e) { throw new RuntimeException(e); } } }
 
PrintWriter 를 이용하면 new OutputStreamWriter(socket.getOutputStream()) 를 socket.getOutputStream() 로 짧게 만들 수 있다. true 는 flush() 의 역할로 반드시 필요하다.
 
public class Server { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(5000); Socket socket = serverSocket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (true) { String reseiveMsg = br.readLine(); System.out.println("클라이언트가 보낸 메세지:" + reseiveMsg); } } catch (IOException e) { throw new RuntimeException(e); } } }
 
 
notion image
 
서버가 클라이언트에게 여러번 메세지를 보낼 수 있다.
 
 

2. 서버 → 클라이언트 채팅 보내기

 
[클라이언트] while (true) { String msg = sc.nextLine(); pw.println(msg); String reseiveMsg = br.readLine(); System.out.println("서버가 보낸 메세지:" + reseiveMsg); }
[서버] while (true) { String reseiveMsg = br.readLine(); System.out.println("클라이언트가 보낸 메세지:" + reseiveMsg); String msg = sc.nextLine(); pw.println(msg); }
 
각 클래스의 반복문에 버퍼를 추가 했다. 실행하면 이런 결과가 나온다.
 
notion image
 
 
메세지 전송은 가능하지만 반복문에서 readLine 과 println 가 순서대로 출력된다.
따라서 서버나 클라이언트는 연달아서 채팅을 할 수 없고 응답이 있어야 메세지가 발송된다.
그래서 동시에 실행을 위해서는 스레드가 필요하다.
 
new Thread(() -> {}).start(); // 스레드 생성 방법
 
이 스레드를 서버와 클라이언트 클래스에 추가한다.
 

3. 스레드를 추가한 전이중 통신

 
[클라이언트] public class Client { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 5000); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); Scanner sc = new Scanner(System.in); new Thread(() -> { while (true) { try { String reseiveMsg = br.readLine(); System.out.println("서버가 보낸 메세지:" + reseiveMsg); } catch (IOException e) { throw new RuntimeException(e); } } }).start(); new Thread(() -> { while (true) { String msg = sc.nextLine(); pw.println(msg); } }).start(); } catch (IOException e) { throw new RuntimeException(e); } } }
[서버] public class Server { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(5000); Socket socket = serverSocket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); Scanner sc = new Scanner(System.in); new Thread(() -> { while (true) { try { String reseiveMsg = br.readLine(); System.out.println("클라이언트가 보낸 메세지:" + reseiveMsg); } catch (IOException e) { throw new RuntimeException(e); } } }).start(); new Thread(() -> { while (true) { String msg = sc.nextLine(); pw.println(msg); } }).start(); } catch (IOException e) { throw new RuntimeException(e); } } }
 
 
코드가 완성 되었다. while 문의 코드를 각각 2개의 스레드로 만들었다. 스레드로 다중 처리가 가능하기 때문에 양방향으로 발신과 수신이 가능하다.
 
notion image
Share article

{CODE-RYU};