
1. 전이중 통신

내가 따로 요청을 안하더라도 동시에 요청하고, 요청받을 수 있는 것 (실시간 채팅)
클라이언트가 언제 요청을 보내고 데이터를 받을지 알 수 없는 상황인 경우,
서버는 클라이언트의 요청을 기다리지 않고, 필요한 시점에 데이터를 쓰고 읽을 수 있다.
서버는 데이터를 언제든지 받을 준비가 되어 있고, (리스너처럼)
클라이언트가 요청을 보내면 그때 데이터를 쓰고 읽을 수 있다는 것.
즉, While 루프를 사용하여 지속적으로 요청을 확인해야 하므로, 스레드(Thread)를 사용
이 스레드는 메세지를 읽기만 하니, 따로 BufferedWrite하는 (쓰기만 하는) 스레드도 필요하다
= 동시에 작업하니 멀티 스레드 사용! (카톡을 생각하면 이해하기가 쉽다)서버는 소켓을 생성하여 클라이언트의 연결을 받아들이고,
클라이언트는 소켓을 생성하여 서버에 연결한다.
[ 전이중 통신 스레드 묶음 ]


전이중은 스테이트 풀 (서버도 상태를 기억하고, 클라이언트도 상태를 기억하기 때문)
2. 전이중 통신 코드 +PrintWriter
1. 서버 생성
2. 클라이언트 생성
3. 클 -> 서버 (메시지를 지속적으로 전송) 지속적으로 = while
4. 서버 -> 클 (메시지를 지속적으로 전송) <- 여기부터 스레드[ 1단계 ]
package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(20000);
Socket socket = serverSocket.accept();
//소켓 연결 완료됨
//버퍼 만들기 (received)
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
//break 없다. 계속 받아야하니까!
while (true) {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메시지 : " + requestMsg);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 20000);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
//메세지 보내는 것만 while 돌면 되겠네?
while (true) {
pw.println("3");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} while (true) {
pw.println("3");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
나중엔 이 부분을 메세지전송() 같은 메소드로 바꿔야한다. 그래야 메소드만 때리면 되니까
계속 3이 찍히는 것 확인! 이 메시지를 키보드로 입력받아 보자![ PrintWriter ]
[ 2단계 ]
package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(20000);
Socket socket = serverSocket.accept();
//소켓 연결 완료됨
//버퍼 만들기 (received)
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
//break 없다. 계속 받아야하니까!
while (true) {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메시지 : " + requestMsg);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 20000);
Scanner sc = new Scanner(System.in);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
//메세지 보내는 것만 while 돌면 되겠네?
while (true) {
String keykboardMsg = sc.nextLine();
pw.println(keykboardMsg);
//키보드에 글 적기 전까지는 대기가 되니까 sleep 필요 없음!!
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

[ 3단계 ] - 스레드 필요!
스레드 돌려서 보내는 것만 할 것임

package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
public class Server {
public static void main(String[] args) {
try {
//1. 소켓과 버퍼 만들기
ServerSocket serverSocket = new ServerSocket(20000);
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
//2. 메시지 받기 스레드
new Thread(() -> {
while (true) {
try {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메시지 : " + requestMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
//1. 소켓과 버퍼 만들기
Socket socket = new Socket("localhost", 20000);
Scanner sc = new Scanner(System.in);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
//메세지 보내는 것만 while 돌면 되겠네?
//2. 메시지 전송 스레드
new Thread(() -> {
while (true) {
//키보드에 글 적기 전까지는 대기가 되니까 sleep 필요 없음!!
String keykboardMsg = sc.nextLine();
pw.println(keykboardMsg);
}
}).start();
//3. 메시지 읽기 스레드
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

[ 4단계 ] - 3단계의 반대를 붙여넣기…
[ 서버 ]
package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
try {
//1. 소켓과 버퍼 만들기
ServerSocket serverSocket = new ServerSocket(20000);
Socket socket = serverSocket.accept();
Scanner sc = new Scanner(System.in);
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//2. 메시지 받기 스레드
new Thread(() -> {
while (true) {
try {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메시지 : " + requestMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
//3. 메시지 쓰기 스레드
new Thread(() -> {
while (true) {
//키보드에 글 적기 전까지는 대기가 되니까 sleep 필요 없음!!
String keykboardMsg = sc.nextLine();
pw.println(keykboardMsg);
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}[ 클라이언트 ]
package ex17.multi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
//1. 소켓과 버퍼 만들기
Socket socket = new Socket("192.168.0.94", 20000);
Scanner sc = new Scanner(System.in);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//메세지 보내는 것만 while 돌면 되겠네?
//2. 메시지 전송 스레드
new Thread(() -> {
while (true) {
//키보드에 글 적기 전까지는 대기가 되니까 sleep 필요 없음!!
String keykboardMsg = sc.nextLine();
pw.println(keykboardMsg);
}
}).start();
//3. 메시지 읽기 스레드
new Thread(() -> {
while (true) {
try {
String requestMsg = br.readLine();
System.out.println("서버로부터 받은 메시지 : " + requestMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
ipconfig로 각자의 ip를 확인. ip와 동일한 포트번호로 연결한 후, a컴퓨터가 서버, b컴퓨터가 클라이언트가 되어서 채팅한 모습
메인은 스레드를 때리는 용도로만 써라!
만약, 코드가 완벽한데 통신이 잘 안된다면 ‘방화벽’ 을 확인할 것!
설정 - 방화벽에서 openjdk
BufferedReader ♥ readLine()
BufferedWriter ♥ flush()
Share article
