본문 바로가기
국비 과정/Java

국비 - 0819 ( 채팅 창 만들기 )

by 코딩호야 2022. 8. 19.

채팅창 만들기 채팅 서버를 먼저 아래코드 처럼 만들어준다.

public class ChatServer extends Frame implements ActionListener {

   Button btn_ext; // 종료 버튼
   TextArea txt_list; // 접속 목록 출력
   protected Vector list; // 접속한 서버 목록 저장
   
   // 생성자
   public ChatServer(String title) {
      super(title); // 타이틀바에 출력될 문자열
      list = new Vector(); // 백터 생성
      btn_ext = new Button("서버 종료"); // 서버 종료 버튼 생성
      btn_ext.addActionListener(this); // 이벤트 등록
      txt_list = new TextArea(); // txt_list 생성
      add("Center", txt_list); // 화면 가윈데 txt_list 출력
      add("South", btn_ext); // 화면 하단에 서버 종료 버튼 출력
      setSize(300, 300); //화면 크기 설정
      setVisible(true);// 화면 출력
      ServerStart(); // 채팅 서버 시작
   }
   
   
   // 채팅 서버				//중요코드
   public void ServerStart() {
      final int port = 7400; // 채팅 서버 포트 상수 지정
      try {
         ServerSocket ss = new ServerSocket(port); //ServerSocket 생성
         while (true) {
            Socket client = ss.accept(); //클라이언트 접속 기다림
            txt_list.append(client.getInetAddress().getHostAddress() + "\n");
            ChatHandle ch = new ChatHandle(this, client); //ChatHandle 초기화
            list.addElement(ch); // 클라이언트 관리 list 백터에 출가
            ch.start(); //ChatHandle 스레드 시작
         }
      } catch (Exception e) { //예외처리
         System.out.println(e.getMessage());
      }
   }
   
   // 서버 종료 버튼이 눌렸을때
   public void actionPerformed(ActionEvent e) {
      System.exit(0);
   }
   
   // 메시지 출력 메서드
   public void setMsg(String msg) {
      txt_list.append(msg + "\n"); // 화면에 msg 메시지 출력
   }
   
   public static void main(String[] args) {
      new ChatServer(" 채팅 서버 ");
   }
}


//ChatHandle 클래스
//채팅 서버의 실질적인 역할 처리

class ChatHandle extends Thread {//스레드 상속

   ChatServer server = null; // GUIChatServer 멤버 변수
   Socket client = null; // 접속한 클라이언트
   BufferedReader br = null; //읽어오기
   PrintWriter pw = null; //보내기
   
   // 생성자
   public ChatHandle(ChatServer server, Socket client) throws IOException {
      this.server = server;
      this.client = client;
      //입출력 스트림 생성
      InputStream is = client.getInputStream();
      br = new BufferedReader(new InputStreamReader(is));
      OutputStream os = client.getOutputStream();
      pw = new PrintWriter(new OutputStreamWriter(os));
   }
   
   // 현재 서버에 접속한 모든 클라이언트에 msg 전송
   public void Send_All(String msg) {
      try {
         synchronized (server.list) { // ChatServer 멤버 변수 list 동기화 처리
            int size = server.list.size(); //현재 접속한 클라이언트 수
            for (int i = 0; i < size; i++) {
               ChatHandle chs = (ChatHandle) server.list.elementAt(i);
               synchronized (chs.pw) { //ChatHandle pw 인스턴스를 이용한 문자 전송ㅁ
                  chs.pw.println(msg);
               }
               chs.pw.flush();
            }
         }
      } catch (Exception e) { //예외처리
         System.out.println(e.getMessage());
      }
   }
   
   // Thread 클래스의 run 메소드 오버라이딩
   @Override
   public void run() {
      String name = "";
      try {
         name = br.readLine(); //대화면 읽어오기
         Send_All(name + " 님이 새로 입장하셨습니다.");
         while (true) {
            String msg = br.readLine(); // 클라이언트 메시지 대기
            String str = client.getInetAddress().getHostName();
            synchronized (server) {
               server.setMsg(str + " : " + msg); // 접속 클라이언트 메시지 출력
            }
            if (msg.equals("@@Exit")) { // @@Exit 메시지면 클라이언트 접속 해지
               break;
            } else { // 현재 접속한 모든 클라이언트에 메시지 전송
               Send_All(name + " >> " + msg);
            }
         }
      } catch (Exception e) { // 예외 처리
         server.setMsg(e.getMessage());
      } finally {
         synchronized (server.list) {
            server.list.removeElement(this); //접속 목록에서 제거
         }
         try { // 스트림 해지
            br.close();
            pw.close();
            client.close(); // 클라이언트 접속 해지
         } catch (IOException e) { //예외처리
            server.setMsg(e.getMessage());
         }
      }
   }
   
}

 

채팅창에 접속할수있는 채팅 클라이언트를 아래코드처럼 만들어준다.

public class ChatClient extends Frame implements ActionListener, Runnable {

	Button btn_exit; // 종료버튼
	Button btn_send; // 문자열 전송
	Button btn_connect; // 서버접속
	TextArea txt_list; // 접속목록 출력
	TextField txt_server_ip; // 접속서버 아이피
	TextField txt_name; // 접속 이름
	TextField txt_input; // 전송메시지
	Socket client; // 접속 클라이언트 소켓
	BufferedReader br = null; // 읽어오기 스트림
	PrintWriter pw = null; // 보내기 스트림
	String server_ip = null; // 서버 아이피
	final int port = 7400; // 포트 번호

	CardLayout c1; // 카드 레이아웃 설정

	// 생성자
	public ChatClient(String title) {
		super(title); // 타이틀바 제목
		c1 = new CardLayout();// 카드 레이아웃 초기화
		setLayout(c1); // 레이아웃 변경
		Panel connect = new Panel(); // 접속화면
		connect.setLayout(new BorderLayout());
		Panel chat = new Panel(); // 채팅화면
		chat.setLayout(new BorderLayout());

		btn_connect = new Button("서버 접속"); // 버튼생성
		btn_connect.addActionListener(this); // 이벤트 등록
		txt_server_ip = new TextField("192.168.20.22", 15); // 192.168.0.90
		txt_name = new TextField("정종호^^", 15);
		Panel connect_sub = new Panel();
		connect_sub.add(new Label("서버 아이피 : "));
		connect_sub.add(txt_server_ip);
		connect_sub.add(new Label("대화명     :"));
		connect_sub.add(txt_name);
		connect.add("North", new Label("다중 채팅 접속 화면 ", Label.CENTER));
		connect.add("Center", connect_sub);
		connect.add("South", btn_connect);

		txt_list = new TextArea();
		txt_input = new TextField("", 25);
		btn_exit = new Button("종료");
		btn_send = new Button("전송");
		btn_exit.addActionListener(this);
		btn_send.addActionListener(this);
		txt_input.addActionListener(this);
		Panel chat_sub = new Panel();
		chat_sub.add(txt_input);
		chat_sub.add(btn_send);
		chat_sub.add(btn_exit);
		chat.add("North", new Label("채팅 프로그램 ver 1.0", Label.CENTER));
		chat.add("Center", txt_list);
		chat.add("South", chat_sub);

		add(connect, "접속창");
		add(chat, "채팅창");

		c1.show(this, "접속창");

		setSize(400, 300);
		setVisible(true);
	}

	// Runnable 인터페이스 run 메서드 오버라이딩
	public void run() {
		try {
			client = new Socket(server_ip, port); // 소켓 생성
			// 입출력 스트림 생성
			InputStream is = client.getInputStream();
			OutputStream os = client.getOutputStream();
			br = new BufferedReader(new InputStreamReader(is));
			pw = new PrintWriter(new OutputStreamWriter(os));
			String msg = txt_name.getText();
			pw.println(msg);
			pw.flush();
			txt_input.requestFocus();
			while (true) {
				msg = br.readLine();
				txt_list.append(msg + "\n");

			}

		} catch (Exception e) { // 예외처리
			System.out.print(e.getMessage());
		}
	}

	public void actionPerformed(ActionEvent e) {
		try {
			Object obj = e.getSource();
			// 서버 접속버튼이 눌렸을때
			if (obj == btn_connect) {
				server_ip = txt_server_ip.getText();
				Thread th = new Thread(this);
				th.start(); // 스레드 시작
				c1.show(this, "채팅창"); // 채팅창으로 화면 전환
			}
			// 종료 버튼이 눌렸을때
			else if (obj == btn_exit) {
				System.exit(0); // 트로그램 강제 종료

			}
			// 전송버튼을 눌렸을때
			// 글입력 상자에서 엔터키를 쳤을때
			else if (obj == btn_send || obj == txt_input) {
				String msg = txt_input.getText();
				pw.println(msg);
				pw.flush();
				txt_input.setText("");
				txt_input.requestFocus();

			}
		} catch (Exception ex) {
			txt_list.append(ex.getMessage() + "\n");
		}

	}

	public static void main(String[] args) {
		new ChatClient("채팅 클라이언트 프로그램");
	}

}

클라이언트 클래스로 서버에 접속하려는 모습이다.

채팅서버로 접속한 모습이다.

위사진처럼 왼쪽에 클라이언트로 접속후 메시지를 전송하면

오른쪽 채팅 창에서 메시지가 출력된다. 이러한 방식으로 채팅창을 만든 후

여러사람이 접속해서 메시지를 주고받을수 있는 채팅창을 만들수 있다.

 

'국비 과정 > Java' 카테고리의 다른 글

국비 - 0818( 네트워크 )  (2) 2022.08.18
국비 - 0804 ( Event )  (0) 2022.08.08
국비 - 0803 ( Text , ScrollPane , Layout)  (0) 2022.08.03
국비 - 0802 ( Checkbox , Scrollbar )  (0) 2022.08.02
국비 - 0801 ( Frame , Button , Label )  (0) 2022.08.01