JAVA 기초

JAVA 23-2

Vanillwa 2023. 9. 12. 21:48

 

실시간 채팅 프로그램 구현하기

 

Server

package ex3_chat;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

//둘 이상의 클라이언트가 접속하며 클라이언트간의 문자전달도 가능한 구조의 서버 구현!
public class ChatServer extends Thread {

	ServerSocket ss;

	ArrayList<CopyClient> list; // 복사본 클라이언트 담을 준비

	public ChatServer() {
		try {
			list = new ArrayList<>(); // 리스트 생성
			ss = new ServerSocket(3200);
			System.out.println("서버 시작!");

		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public static void main(String[] args) {
		new ChatServer().start();
	}

	@Override
	public void run() {
		while (true) {
			try {
				Socket s = ss.accept();
				String ip = s.getInetAddress().getHostAddress();
				System.out.println(ip + "님 접속");

				CopyClient cc = new CopyClient(s, this);
				list.add(cc);
				cc.start(); // 복사 클라이언트의 스레드를 구동
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}

	public void sendMessage(String msg) {
		// 접속자들은 CopyClient로 만들어져 ArrayList에 저장된 상태
		try {
			for (CopyClient cc : list) {
				cc.out.println(msg);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public void removeClient(CopyClient cc) {
		list.remove(cc); // 인자로 전달된 CopyClient 객체를 리스트에서 삭제
		sendMessage("====" + cc.ip + "님 퇴장====");
	}
}

 

 

Client 1

package ex3_chat;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ChatClient extends JFrame implements Runnable {
	// 화면 구성 객체
	JTextArea area; // 채팅을 화면에 출력하는 공간
	JTextField input; // 채팅을 입력하는 공간
	JButton send_bt; // 채팅 전송 버튼
	JPanel south_p;

	// 서버 접속 객체
	Socket s;
	BufferedReader in;
	PrintWriter out;
	Thread t;

	public ChatClient() {
		area = new JTextArea();
		this.add(area);

		// BorderLayout 배치관리자로 지정된 JPanel 생성
		south_p = new JPanel(new BorderLayout());
		south_p.add(input = new JTextField());
		south_p.add(send_bt = new JButton("보내기"), BorderLayout.EAST);

		this.add(south_p, BorderLayout.SOUTH);

		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				out.println("xx:~X"); // 종료시 xx:~X라는 메세지 전달
			}
		});

		send_bt.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				sendData(); // 서버로 메세지를 전달하기 위한 메서드
			}
		});

		setBounds(300, 300, 400, 500);
		setVisible(true);

		connected(); // 서버에 접속하기 위한 메서드

		t = new Thread(this);
		t.start();
	}

	public void connected() {
		try {
			s = new Socket("ip 주소 입력", 3200);
			in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			out = new PrintWriter(s.getOutputStream(), true);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public static void main(String[] args) {
		new ChatClient();
	}

	@Override
	public void run() {
		while (true) {
			try {
				String msg = in.readLine();
				if (msg.equals("xx:~X")) {
					break;
				}
				if (msg != null) {
					area.append(msg + "\r\n");
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}

		closed(); // 열려있는 스트림을 닫는 메서드
		System.exit(0); // 프로그램 종료
	}

	public void sendData() {
		String msg = input.getText().trim();
		if (msg.length() > 0) { // 한글자라도 입력했을 때 서버로 전송
			out.println(msg);
		}
		input.setText(""); // 텍스트필드 비우기
	}

	public void closed() {
		try {
			if (out != null)
				out.close();
			if (in != null)
				in.close();
			if (s != null)
				s.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

 

 

Client 2

package ex3_chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class CopyClient extends Thread {
	Socket s;
	BufferedReader in;
	PrintWriter out;
	ChatServer server;
	String ip;

	public CopyClient(Socket s, ChatServer server) {
		this.s = s;
		this.server = server;

		try {
			out = new PrintWriter(s.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			ip = s.getInetAddress().getHostAddress();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	@Override
	public void run() {
		while (true) {
			try {
				String msg = in.readLine();
				if (msg.equals("xx:~X")) {
					out.println("xx:~X");
					server.removeClient(this);
					break;
				}
				server.sendMessage(ip + " : " + msg);
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
}

 

 

실행 결과

Server측 콘솔에서 Client 1 과 Client 2가 접속된 모습

 

 

Client 1이 친 채팅이 Client 2 프레임에도 나타나는 모습

 

 

 

Client 2가 보낸 채팅도 정상적으로 출력된다

 

 

 

Client 1이 종료할 경우 Client 2 프레임에선 Client 1이 퇴장했다고 출력 된다.

 

 


 

'JAVA 기초' 카테고리의 다른 글

JAVA 24  (0) 2023.09.13
JAVA 23-1  (0) 2023.09.12
JAVA 22-2  (0) 2023.09.12
JAVA 22-1  (0) 2023.09.12
JAVA 21-2  (0) 2023.09.08