반응형

# Java Socket(소켓)을 이용한 Multi-Chatting 프로그래밍

  • 멀티 채팅 구현 작업 진행.
  • 서버에서 HashMap 이용하여 멀티 채팅 구현.
  • 연결, 접속에 따른 알림 표시. 
  • 서버 : 서버에서는 HashMap 이용하여 클라이언트 관련 정보 담고, Thread를 이용하여 HashMap에 저장된 클라이언트 정보를 바탕으로 브로드 캐스팅 진행.
  • 클라이언트 : 보내는 쪽은 sender 라는 Thread 에 소켓 정보와 클라이언트 정보를 서버에 보내서 작업. 받는 쪽은 receiver 라는 Thread 에 소켓 정보를 담아 데이터 수신.

## 작업 소스

Project06F_MultiChatServer

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;

public class Project06F_MultiChatServer {
	HashMap clients;
	
	Project06F_MultiChatServer() {
		clients = new HashMap();
		Collections.synchronizedMap(clients);	// 동기화를 위해 사용.
	}
	
	public void start() {
		ServerSocket serverSocket = null;
		Socket socket = null;
		
		try {
			serverSocket = new ServerSocket(9999);
			System.out.println("서버 실행...");
			
			while (true) {
				socket = serverSocket.accept();	// 클라이언트의 정보를 알고 있는 소켓.
				System.out.println(socket.getInetAddress() + ":" + socket.getPort() + " 연결.");
				
				ServerReceiver thread = new ServerReceiver(socket);
				thread.start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 브로드캐스팅 기능
	void sendToAll(String msg) {
		Iterator iterator = clients.keySet().iterator();
		
		while (iterator.hasNext()) {
			try {
				DataOutputStream out = (DataOutputStream) clients.get(iterator.next());
				out.writeUTF(msg);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] agrg) {
		new Project06F_MultiChatServer().start();
	}
	
	// inner class (클래스 내부에 있는 클래스를 의미)
	public class ServerReceiver extends Thread {
		Socket socket;
		DataInputStream in;
		DataOutputStream out;
		
		ServerReceiver(Socket socket) {
			this.socket = socket;
			
			try {
				in = new DataInputStream(socket.getInputStream());
				out = new DataOutputStream(socket.getOutputStream());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void run() {
			String name = "";
			
			try {
				name = in.readUTF();
				
				// HashMap 에 사용자 이름 존재유무 체크.
				if (clients.get(name) != null) {
					out.writeUTF("이미 존재하는 이름입니다 : " + name);
					out.writeUTF("다른 이름으로 다시 연결해주세요.");
					System.out.println(socket.getInetAddress() + ":" + socket.getPort() + " 연결 종료.");
					in.close();
					out.close();
					socket.close();
					socket = null;
				} else {
					sendToAll("#" + name + " 님께서 입장하셨습니다.");
					clients.put(name, out);
					
					while (in != null) {
						sendToAll(in.readUTF());
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (socket != null) {
					sendToAll("#" + name + " 님께서 접속을 종료하였습니다.");
					clients.remove(name);
					System.out.println(socket.getInetAddress() + ":" + socket.getPort() + " 연결 종료.");
				}
			}
		}
	}
}

Project06F_MultiChatClient

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Project06F_MultiChatClient {
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1", 9999);
			Scanner scanner = new Scanner(System.in);
			
			System.out.println("name : ");
			String name = scanner.nextLine();
			
			Thread sender = new Thread(new ClientSender(socket, name));
			Thread receiver = new Thread(new ClientReceiver(socket));
			sender.start();
			receiver.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// inner class
	static class ClientSender extends Thread {
		Socket socket;
		DataOutputStream out;
		String name;
		
		ClientSender(Socket socket, String name) {
			this.socket = socket;
			this.name = name;
			try {
				out = new DataOutputStream(socket.getOutputStream());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void run() {
			Scanner scanner = new Scanner(System.in);
			
			try {
				if (out != null) {
					out.writeUTF(name);
				}
				
				while (out != null) {
					String message = scanner.nextLine();
					
					if (message.equals("quit")) {
						break;
					}
					out.writeUTF("[" + name + "] : " + message);
				}
				out.close();
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	static class ClientReceiver extends Thread {
		Socket socket;
		DataInputStream in;
		
		ClientReceiver(Socket socket) {
			this.socket = socket;
			
			try {
				in = new DataInputStream(socket.getInputStream());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void run() {
			while (in != null) {
				try {
					System.out.println(in.readUTF());
				} catch (Exception e) {
					e.printStackTrace();
					break;
				}
			}
			
			try {
				in.close();
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

## 실행방법

서버 실행

  • 관리자 권한으로 cmd 실행
  • 워크스페이스의 bin 폴더까지 들어간 후 java Project06F_MultiChatServer 입력하여 서버 실행.

클라이언트 실행

  • 관리자 권한으로 cmd 실행
  • 워크스페이스의 bin 폴더까지 들어간 후 java Project06F_MultiChatClient 입력하여 서버 실행. (멀티 채팅이므로 cmd 하나 더 실행해서 동일하게 실행)
반응형

+ Recent posts