본문 바로가기
Java/Java

네트워크) TCP 소켓 프로그래밍 (채팅 프로그램 만들기)

by 박채니 2022. 4. 11.
SMALL

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


TCP 소켓 프로그래밍

- 클라이언트와 서버간의 1:1 소켓 통신

- 서버가 먼저 실행되어 클라이언트의 연결 요청을 기다려야 함

- java.net 패키지에서 제공하는 ServerSocket과 Socket 클래스가 해당

- 서버용 프로그램과 클라이언트용 프로그램을 따로 구현

 

싱글 스레드로 채팅 프로그램 만들기

Server 

public class ChatServer {
	
	public static final int PORT = 7777;
	
	public static void main(String[] args) {
		new ChatServer().start();
	}
	
	public void start() {
		try {
			//1. Socket 생성(PORT)
			ServerSocket serverSocket = new ServerSocket(PORT);
			InetAddress serverInetAddress = InetAddress.getLocalHost();
			
			while(true) {
				System.out.printf("[%s:%d] ChatServer 연결대기중...\n", serverInetAddress.getHostAddress(), PORT);
				
				//2. 클라이언트 요청이 올 때까지 실행 대기
				Socket socket = serverSocket.accept();
				System.out.printf("[%s]로부터 연결요청...\n", socket.getInetAddress().getHostAddress());
				
				//3. 입출력스트림 준비
				BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
//				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
				PrintWriter pw = new PrintWriter(socket.getOutputStream()); //바이트기반도 브릿지 스트림 없이 받을 수 있음! 개행문자까지 읽어옴
				Scanner sc = new Scanner(System.in);
				pw.println("환영합니다😊🎉");
				pw.flush();
				
				String inMsg = null;
				while((inMsg = br.readLine()) != null) {
					if("exit".equals(inMsg)) {
						System.out.println("> 상대가 채팅방을 나갔습니다.");
						break;
					}
					
					System.out.println("클라이언트 : " + inMsg);
					System.out.print("서버 : ");
					String outMsg = sc.nextLine();
					pw.println(outMsg);
					pw.flush();
					
					if("exit".equals(outMsg)) {
						break;
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("> 프로그램을 종료합니다.");
	}
}

 

Client

public class ChatCilent {
	
	public static final String SERVER_IP = "localhost";
	public static final int SERVER_PORT = 7777;
	
	public static void main(String[] args) {
		new ChatCilent().start();
	}
	
	public void start() {
		try {
			//1. Socket 객체 생성(IP, PORT)
			Socket clientSocket = new Socket(SERVER_IP, SERVER_PORT);
			System.out.printf("[%s:%d]에 접속 중...\n", SERVER_IP, SERVER_PORT);
			
			//2. 입출력 스트림 준비
			BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());
			Scanner sc = new Scanner(System.in);
			
			String inMsg = null;
			while((inMsg = br.readLine()) != null) {
				if("exit".equals(inMsg)) {
					System.out.println("> 상대가 채팅방을 나갔습니다.");
					break;
				}
				
				System.out.println("서버 : " + inMsg);
				System.out.print("클라이언트 : ");
				String outMsg = sc.nextLine();
				pw.println(outMsg);
				pw.flush();
				
				if("exit".equals(outMsg)) {
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("> 프로그램을 종료합니다.");
	}
}

 

멀티 쓰레드로 채팅 프로그램 만들기

Server

public class ChatServer {
	public static final int PORT = 7777;
	
	public static void main(String[] args) {
		new ChatServer().start();
	}
	
	public void start() {
		try {
			ServerSocket serverSocket = new ServerSocket(PORT);
			
			while(true) {
				System.out.printf("[%s:%d] 서버 대기 중...\n", InetAddress.getLocalHost().getHostAddress(), PORT);
				Socket socket = serverSocket.accept();
				
				//입력쓰레드, 출력쓰레드 각각 생성해서 시작
				Thread sender = new Thread(new Sender(socket));
				Thread receiver = new Thread(new Receiver(socket));
				sender.start();
				receiver.start();
				System.out.println("채팅을 시작합니다.");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

Client

public class ChatClient {
	public static final String SERVER_IP = "localhost";
	public static final int SERVER_PORT = 7777;
	
	public static void main(String[] args) {
		new ChatClient().start();
	}
	
	public void start() {
		try {
			Socket clientSocket = new Socket(SERVER_IP, SERVER_PORT);
			
			//입력쓰레드, 출력쓰레드 각각 생성해서 시작
			Thread sender = new Thread(new Sender(clientSocket));
			Thread receiver = new Thread(new Receiver(clientSocket));
			sender.start();
			receiver.start();
			System.out.println("채팅을 시작합니다.");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

Sender(Thread)

public class Sender implements Runnable {
	
	private PrintWriter pw;
	private Scanner sc = new Scanner(System.in);
	
	public Sender(Socket socket) {
		try {
			pw = new PrintWriter(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	

	@Override
	public void run() {
		while(true) {
			String outMsg = sc.nextLine();
			
			pw.println(outMsg);
			pw.flush();
			
			if("exit".equals(outMsg)) {
				break;
			}
		}
		System.out.println("> 채팅을 종료합니다.");
	}
}

 

Receiver(Thread)

public class Receiver implements Runnable {
	
	private BufferedReader br;
	private String name;
	
	public Receiver(Socket socket) {
		try {
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			name = "[" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "]";
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		while(true) {
			try {
				String inMsg = br.readLine();
				
				if("exit".equals(inMsg)) {
					break;
				}
				System.out.println(name + " " + inMsg);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("> 상대방이 채팅방을 나갔습니다.");
	}
}

 

 

LIST