IT 개발/Java

[Java] 자바 - 멀티채팅 프로그램 구현하기

KADOSHOLY 2022. 8. 10. 19:27
반응형

 

자바 - 멀티채팅 프로그램 구현하기

 

 

앞서 자바 소켓통신 내용에서는 TCP/IP기반 통신에서 서버와 클라이언트가 데이터를 서로 주고 받는 법에 대해서 알아보았습니다. 여기에서는 멀티스레드를 이용하여 멀티채팅 프로그램을 구현하는 방법에 대해서 알아보도록 하겠습니다. 

 

2022.08.08 - [IT 개발/Java] - [Java] 자바 - 소켓통신이란? 소켓(Socket) 개념과 사용방법

 

[Java] 자바 - 소켓통신이란? 소켓(Socket) 개념과 사용방법

자바 - 소켓통신이란? 소켓(Socket) 개념과 사용방법 네트워크를 통해 데이터를 주고받을 수 있도록 지원하는 소켓(Socket) 통신에 대해서 알아보도록 하겠습니다.  목차 소켓(socket)과 소켓통신이란

kadosholy.tistory.com

 

 

   목차

  1. 서버 구현
  2. 클라이언트 구현
  3. 멀티채팅 프로그램 실행결과

 

 

1. 서버 구현

 

멀티채팅 프로그램에서 서버에서는 서버소켓이 루프를 돌면서 클라이언트가 연결될때마다 새로운 스레드(ReceiveThread)를 생성합니다. 그리고 이렇게 생성된 스레드는  클라이언트에서 메시지가 들어올때마다 전체 클라이언트에 해당 메시지를 전송합니다. 

 

멀티채팅에서 서버와 클라이언트의 관계도
멀티채팅 - 서버와 클라이언트

 

public class MultiServer {
	
	public static void main(String[] args) {
		MultiServer multiServer = new MultiServer();
		multiServer.start();
	}
	
	public void start() {
		ServerSocket serverSocket = null;
		Socket socket = null;
		try {
			serverSocket = new ServerSocket(8000);
			while (true) {
				System.out.println("[클라이언트 연결대기중]");
				socket = serverSocket.accept();
				
				// client가 접속할때마다 새로운 스레드 생성
				ReceiveThread receiveThread = new ReceiveThread(socket);	
				receiveThread.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (serverSocket!=null) {
				try {
					serverSocket.close();
					System.out.println("[서버종료]");
				} catch (IOException e) {
					e.printStackTrace();
					System.out.println("[서버소켓통신에러]");
				}
			}
		}
	}
}

class ReceiveThread extends Thread {
	
	static List<PrintWriter> list = 
			Collections.synchronizedList(new ArrayList<PrintWriter>());
	
	Socket socket = null;
	BufferedReader in = null;
	PrintWriter out = null;
			
	public ReceiveThread (Socket socket) {
		this.socket = socket;
		try {
			out = new PrintWriter(socket.getOutputStream());
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			list.add(out);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
		
	@Override
	public void run() {

		String name = "";
		try {
			// 최초1회는 client이름을 수신
			name = in.readLine();
			System.out.println("[" + name + " 새연결생성]");	
			sendAll("[" + name + "]님이 들어오셨습니다.");
			
			while (in != null) {
				String inputMsg = in.readLine();
				if("quit".equals(inputMsg)) break;
				sendAll(name + ">>" + inputMsg);
			}
		} catch (IOException e) {
			System.out.println("[" + name + " 접속끊김]");
		} finally {
			sendAll("[" + name + "]님이 나가셨습니다");
			list.remove(out);
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("[" + name + " 연결종료]");
	}
	
	private void sendAll (String s) {
		for (PrintWriter out: list) {
			out.println(s);
			out.flush();
		}
	}
}

 

반응형

 

 

2. 클라이언트 구현

 

클라이언트에서는 서버로부터 메시지를 전송받아 화면에 출력합니다. 그리고 메시지를 입력받아 서버에 전송하기 위한 스레드 하나를 생성하고, 첫전송은 client들의 구분을 위해서 client 이름을 생성해 전송하도록 합니다. 

 

public class MultiClient {
	
	public static void main(String[] args) {
		MultiClient multiClient = new MultiClient();
		multiClient.start();
	}
	
	public void start() {
		Socket socket = null;
		BufferedReader in = null;
		try {
			socket = new Socket("localhost", 8000);
			System.out.println("[서버와 연결되었습니다]");

			String name = "user" + (int)(Math.random()*10);
			Thread sendThread = new SendThread(socket, name);
			sendThread.start();

			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while (in != null) {
				String inputMsg = in.readLine();
				if(("[" + name + "]님이 나가셨습니다").equals(inputMsg)) break;
				System.out.println("From:" + inputMsg);
			}
		} catch (IOException e) {
			System.out.println("[서버 접속끊김]");
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("[서버 연결종료]");
	}
}

class SendThread extends Thread {
	Socket socket = null;
	String name;

	Scanner scanner = new Scanner(System.in);
	
	public SendThread(Socket socket, String name) {
		this.socket = socket;
		this.name = name;
	}

	@Override
	public void run() {
 		try {
			// 최초1회는 client의 name을 서버에 전송
			PrintStream out = new PrintStream(socket.getOutputStream());
			out.println(name);
			out.flush();
			
			while (true) {
				String outputMsg = scanner.nextLine();
				out.println(outputMsg);
				out.flush();
				if("quit".equals(outputMsg)) break;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}
}

 

 

 

3. 멀티채팅 프로그램 실행결과

 

먼저 서버를 실행시킨후 클라이언트 두개를 실행시킨결과합니다. 

  1. 좌측 : 서버
  2. 중앙 : 클라이언트1 - user5
  3. 우측 : 클라이언트2 - user4

 

멀티채티프로그램 실행결과
멀티채팅 프로그램 실행결과 : (좌측)서버 - (중앙)클라이언트1 [user5] - (우측)클라이언트2 [user4]

 

 

반응형