전이중 통신은 채팅 처럼 양방향에서 동시에 통신이 가능한 방식이다.
자바를 통해 채팅이 가능한 코드를 만들어보자.
소켓과 버퍼에 관한 내용은 아래의 블로그에서 확인할 수 있다.
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); } } }
서버가 클라이언트에게 여러번 메세지를 보낼 수 있다.
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); }
각 클래스의 반복문에 버퍼를 추가 했다. 실행하면 이런 결과가 나온다.
메세지 전송은 가능하지만 반복문에서 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개의 스레드로 만들었다. 스레드로 다중 처리가 가능하기 때문에 양방향으로 발신과 수신이 가능하다.
Share article