
오늘은 자바를 공부하면서 소규모 프로젝트로 멀티 스레드를 활용한 다중 클라이언트 채팅 프로그램을 만들어 보았습니다.
채팅 프로그램의 작업 흐름
- 서버 쪽에서 SeverSocket을 생성
- 클라이언트 쪽에서 해당 IP에 Socket을 생성
- 서버쪽에서 접속하려는 클라이언트를 accept()하고 리스트에 클라이언트 저장
- 클라이언트가 작업 요청 (채팅 프로그램이니 작업은 메세지 전송)
- 서버 쪽 스레드에서 요청을 처리
- 응답을 클라이언트에게 반환
- 받은 메세지를 리스트에 있는 모든 클라이언트들에게 전달
- 이유는 단체 채팅방에 있는 모든 유저는 채팅을 보낸 유저의 채팅을 볼수 있어야 하기 때문
package step6;
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.util.ArrayList;
/*
Chatting 서버
1. 클라이언트의 접속 -> ServerWorker Thread 생성 및 start
2. ServerWorker -> 개별 client에 채팅 서비스
*/
public class ChatServer {
private ArrayList<ServerWorker> list = new ArrayList<ServerWorker>();
public void go() throws IOException {
ServerSocket serverSocket = null;
try {
// 채팅 서버 시작
serverSocket = new ServerSocket(5432);
System.out.println("**step6.ChatServer**");
// 다수의 클라이언트에게 지속적으로 서비스하기 위해 while 이용
while (true) {
Socket socket = serverSocket.accept();
ServerWorker sw = new ServerWorker(socket);
list.add(sw);
Thread thread = new Thread(sw);
thread.start();
}
} finally {
if (serverSocket != null)
serverSocket.close();
System.out.println("**ChatServer 종료합니다**");
}
}
public void sendMessage(String message) {
System.out.println(message);
// 접속해 있는 모든 클라이언트들에게 메세지 전송
for (int i=0;i<list.size();i++) {
list.get(i).pw.println(message);
}
}
class ServerWorker implements Runnable {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
private String user;
public ServerWorker(Socket socket) {
super();
this.socket = socket;
user = socket.getInetAddress().toString();
}
public void chatting() throws IOException {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(),true);
sendMessage(user+"님이 입장하셨습니다");
try {
while (true) {
String message = br.readLine();
if (message.trim().equals("종료") || message.equals("null") || message == null) {
break;
}
sendMessage(user+"님:"+message);
} // while
} // echo method
catch (Exception e) {
}
}
public void run() {
try {
chatting();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
closeAll();
} catch (IOException e) {
e.printStackTrace();
}
sendMessage(user+"님이 나가셨습니다!!");
list.remove(this);
}
}
public void closeAll() throws IOException {
if (pw != null)
pw.close();
if (br != null)
br.close();
if (socket != null)
socket.close();
}
}
public static void main(String[] args) {
try {
new ChatServer().go();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package step6;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import step1.IP;
/*
채팅 클라이언트
스레드 ( 세부적 실행단위 )
1. ReceiverWorker implements Runnable : 친구들의 메세지를 입력받는 역할
2. ChatClient의 main thread : ReceiverWorker Thread 생성 start
자신은 친구들에게 메세지를 출력하는 역할
*/
public class ChatClient {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
private Scanner sc;
public void go() throws UnknownHostException, IOException {
try {
socket = new Socket(IP.LOCAL, 5432);
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(),true);
sc = new Scanner(System.in);
ReceiverWorker rw = new ReceiverWorker();
Thread thread = new Thread(rw);
thread.setDaemon(true);
thread.start();
System.out.println("**ChatClient가 서버에 접속**");
while (true) {
//System.out.print("서버에 보낼 메세지:");
String message = sc.nextLine();
pw.println(message);
if (message.trim().equals("종료")) {
System.out.println("**ChatClient 종료합니다**");
break;
}
}
}finally {
closeAll();
}
}
class ReceiverWorker implements Runnable {
public void run() {
try {
receiveMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
public void receiveMessage() throws IOException {
while (true) {
String message = br.readLine();
if (message == null) {
break;
}
System.out.println(message);
System.out.print("서버에 보낼 메세지:");
}
}
}
public static void main(String[] args) {
ChatClient client = new ChatClient();
try {
client.go();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void closeAll() throws IOException {
if (pw != null)
pw.close();
if (sc != null)
sc.close();
if (br != null)
br.close();
if (socket != null)
socket.close();
}
}