23.02.02(Java)

MH S·2023년 2월 3일

Java

목록 보기
14/16

소켓

  1. 챗팅 클라이언트 예제
package net;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.JTextField;

public class ChatClient1 extends JFrame implements ActionListener, Runnable {

	JButton btn1, btn2;
	JTextField tf1, tf2;
	TextArea ta;
	JPanel p1, p2;
	BufferedReader in;
	PrintWriter out;
	String id;
	public static final int PORT = 8001;

	public ChatClient1() {
		setSize(350, 400);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("MyChat 1.0");
		p1 = new JPanel();
		p1.setBackground(new Color(100, 200, 100));
		p1.add(new Label("HOST ", Label.CENTER));
		p1.add(tf1 = new JTextField("127.0.0.1", 15));
		p1.add(btn1 = new JButton("Connect"));

		p2 = new JPanel();
		p2.setBackground(new Color(100, 200, 100));
		p2.add(new Label("CHAT ", Label.CENTER));
		p2.add(tf2 = new JTextField("", 15));
		p2.add(btn2 = new JButton("SEND"));

		tf1.addActionListener(this);
		tf2.addActionListener(this);
		btn1.addActionListener(this);
		btn2.addActionListener(this);

		add(p1, BorderLayout.NORTH);
		add(ta = new TextArea());
		add(p2, BorderLayout.SOUTH);
		setVisible(true);
		validate();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if (obj == tf1 || obj == btn1 /* connecet */) {
			connect(tf1.getText().trim());
			tf1.setEnabled(false);
			btn1.setEnabled(false);
			tf2.requestFocus();
		} else if (obj == tf2 || obj == btn2 /* send */) {
			String str = tf2.getText().trim();
			if (str.length() == 0)
				return; // 서버로 전송하지 않고 메소드 빠져 나감
			if (id == null) { // 최초 한번만 실행
				id = str;
				setTitle(getTitle() + " [" + id + "]");
				ta.setText("채팅을 시작합니다\n");
			}
			out.println(str); // 서버 전송
			tf2.setText("");
			tf2.requestFocus();
		}
	}// --actionPerformed

	@Override
	// 서버로 부터 메세지가 들어오면 반응하는 기능
	public void run() {
		try {
			while (true) {
				ta.append(in.readLine() + "\n");
				tf2.requestFocus();
			}
		} catch (Exception e) {
			System.err.println("Error in run");
			e.printStackTrace();
			System.exit(1);
		}
	}// --run

	public void connect(String host) {
		try {
			Socket sock = new Socket(host, PORT);
			in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
			out = new PrintWriter(sock.getOutputStream(), true);
			// 서버에서 최초로 보내는 메시지 전달
			ta.append(in.readLine() + "\n");
			tf2.requestFocus();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// Thread Start -> run 메소드 호출
		new Thread(this).start();
	}// --connect

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

챗팅 서버

package net;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

public class ChatServer1 {
	
	public static final int PORT = 8001;
	ServerSocket server;
	Vector<ClientThread1> vc;
	
	public ChatServer1() {
		try {
			server = new ServerSocket(PORT);
			vc = new Vector<ClientThread1>();
		} catch (Exception e) {
			// e.printStackTrace();
			System.err.println("Error in Server");
			System.exit(1); // 비정상적인 종료	
		}
		System.out.println("******************************");
		System.out.println("ChatServer1 v1.0 시작되었습니다");
		System.out.println("******************************");
		try {
			while(true) {
				Socket sock = server.accept();
				ClientThread1 ct = new ClientThread1(sock);
				ct.start();
				// 접속한 클라이언트 Socket 객체를 Vector에 저장
				vc.addElement(ct);
			}
		} catch (Exception e) {
			// e.printStackTrace();
			System.out.println("Error in Socket");
		}
	}
	
	// 전체 접속자에게 메세지 전달
	public void sendAllMessage(String msg) {
		for (int i = 0; i< vc.size(); i++) {
			ClientThread1 ct = vc.get(i);
			ct.sendMessage(msg);
		}
	}
	// 접속이 끊어진 Client를 Vector에서 제거
	public void removeClient(ClientThread1 ct) {
		vc.remove(ct);
	}
	
	class ClientThread1 extends Thread{
		
		Socket sock;
		BufferedReader in;
		PrintWriter out;
		String id;
		
		public ClientThread1(Socket sock) {
			try {
				this.sock = sock;
				in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
				out = new PrintWriter(sock.getOutputStream(), true);
				// sock.toString
				System.out.println(sock.toString() + "접속됨...");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		@Override
		public void run() {
			try {
				// Client에게 최초로 보내는 메세지
				out.println("사용하실 아이디를 입력하세요");
				// Client에서 입력한 id를 저장
				id = in.readLine();
				// 접속한 모든 Client에게 welcome 메세지 전달
				sendAllMessage("[" + id + "]님이 입장하셨습니다.");
				String line = "";
				while(true) {
					if(line == null)
						break; // Client 접속 종료
					sendAllMessage("[" + id + "]"+  line );
				}
				in.close();
				out.close();
				sock.close();
			} catch (Exception e) {
				// 자신의 객체를 Vector에서 제거
				removeClient(this);
				System.err.println(sock + "끊어짐 .......");
			}
		}
		// Client에게 메세지 보내는 메소드
		public void sendMessage(String msg) {
			out.println(msg);
		}
		
	}

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

}

  1. 챗팅 서버2.0 예제
    ChatProtocol2
package net;

public class ChatProtocol2 {
	// ID, CHAT, CHATALL, MESSAGE, CHATLIST
	
	// (C -> S) : ID: aaa
	// (S -> C) CHATLIST;aaa;bbb;ccc;홍길동;
	public static final String ID = "ID";
	
	// (C -> S) CHAT:받는 아이디;메시지 ex) CHAT:bbb; 밥먹자
	// (S -> C) CHAT:보내는 아이디;메시지 ex) CHAT:aaa; 밥먹자
	public static final String CHAT = "CHAT";
	
	
	// (C -> S) CHATALL: 메세지
	// (S -> C) CHATALL:[보내는 아이디] 메세지
	public static final String CHATALL = "CHATALL";
	// (C -> S) MESSAGE :받는아이디;쪽지내용 ex)MESSAGE:bbb; 밥먹자
	// (S -> C) MESSAGE :보내는아이디;쪽지내용 ex)MESSAGE:aaa; 밥먹자
	public static final String MESSAGE = "MESSAGE";
	
	// (S -> C) CHATLIST:aaa;bbb;ccc;홍길동'
	public static final String CHATLIST = "CHATLIST";
	
	public static final String MODE = ":";
	
}

ChatServer2

package net;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

public class ChatServer2 {
	public static final int PORT = 8002;
	ServerSocket server;
	Vector<ClientThread2> vc;

	public ChatServer2() {
		try {
			server = new ServerSocket(PORT);
			vc = new Vector<ClientThread2>();
		} catch (Exception e) {
			System.err.println("Error in Server");
			System.exit(1); // 비정상적인 종료
		}
		System.out.println("*******ChatServer2 v2.0*******");
		System.out.println("***클라이언트 접속을 기다리고 있습니다***");
		System.out.println("******************************");
		try {
			while (true) {
				Socket sock = server.accept();
				ClientThread2 ct = new ClientThread2(sock);
				ct.start();
				// 접속한 클라이언트 Socket 객체를 Vector에 저장
				vc.addElement(ct);
			}
		} catch (Exception e) {
			// e.printStackTrace();
			System.out.println("Error in Socket");
		}
	}

	public void sendAllMessage(String msg) {
		for (int i = 0; i < vc.size(); i++) {
			ClientThread2 ct = vc.get(i);
			ct.sendMessage(msg);
		}
	}

	public void removeClient(ClientThread2 ct) {
		vc.remove(ct);
	}

	// 접속된 모든 id 리스트 리턴 ex)aaa;bbb;홍길동;강호동;
	public String getIdList() {
		String list = "";
		for (int i = 0; i < vc.size(); i++) {
			ClientThread2 ct = vc.get(i);
			list += ct.id + ";";
		}
		return list;
	}

	// 매개변수 id 값으로 ClientThread2를 검색
	public ClientThread2 findClient(String id) {
		ClientThread2 ct = null;
		for (int i = 0; i < vc.size(); i++) {
			ct = vc.get(i);
			if (ct.id.equals(id)) // 매개변수의 id와 ct의 id가 동일 하다면.
				break;
		}
		return ct;
	}

	class ClientThread2 extends Thread {
		Socket sock;
		BufferedReader in;
		PrintWriter out;
		String id;

		public ClientThread2(Socket sock) {
			try {
				this.sock = sock;
				in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
				out = new PrintWriter(sock.getOutputStream(), true);
				// sock.toString
				System.out.println(sock.toString() + "접속됨...");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			try {
				sendMessage("사용하실 아이디를 입력하세요");
				while (true) {
					String line = in.readLine();
					if (line == null)
						break;
					else
						routine(line);
				}
			} catch (Exception e) {
				removeClient(this);
				System.err.println(sock + "[" + id + "] 끊어짐...");
			}
		}

		public void routine(String line) {
			// CHATALL:오늘은 목요일입니다.
			int idx = line.indexOf(ChatProtocol2.MODE);
			String cmd = line.substring(0, idx); // CHATALL
			String data = line.substring(idx + 1); // 오늘은 목요일입니다.
			if(cmd.equals(ChatProtocol2.ID)) {
				id = data;
				// 새로운 접속자 추가 되었기 때문에 리스트 재전송
				sendAllMessage(ChatProtocol2 .CHATLIST+
						ChatProtocol2.MODE+getIdList());
				// 새로운 접속자 welcome 전송
				sendAllMessage(ChatProtocol2.CHATALL+
						ChatProtocol2.MODE + "[" + id + "]님이 입장하였습니다.");
			}else if(cmd.equals(ChatProtocol2.CHATALL)) {
				sendAllMessage(ChatProtocol2.CHATALL+
						ChatProtocol2.MODE + "[" + id + "]" + data);
			}
		}

		public void sendMessage(String msg) {
			out.println(msg);
		}
	} // -- ClientThread2

	public static void main(String[] args) {
		new ChatServer2();
//		String str = "CHATALL:오늘은 목요일입니다.";
//		int idx = str.indexOf(':');
//		System.out.println(str.substring(0,idx));
//		System.out.println(str.substring(idx+1));
	}
}

ChatClient2

package net;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
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 java.util.StringTokenizer;

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

public class ChatClient2 extends JFrame implements ActionListener, Runnable {

	JButton bt1, bt2, bt3, bt4;
	JTextField tf1, tf2, tf3;
	TextArea area;
	List list;
	Socket sock;
	BufferedReader in;
	PrintWriter out;
	String listTitle = "*******대화자명단*******";
	boolean flag = false;

	public ChatClient2() {
		setSize(450, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("MyChat v2.0");
		JPanel p1 = new JPanel();
		p1.add(new Label("Host", Label.RIGHT));
		p1.add(tf1 = new JTextField("127.0.0.1", 10));
		p1.add(new Label("Port", Label.RIGHT));
		p1.add(tf2 = new JTextField("8002", 5));
		bt1 = new JButton("connect");
		bt1.addActionListener(this);
		p1.add(bt1);
		add(BorderLayout.NORTH, p1);
		// //////////////////////////////////////////////////////////////////////////////////////////
		area = new TextArea("MyChat v2.0");
		area.setBackground(Color.DARK_GRAY);
		area.setForeground(Color.PINK);
		area.setEditable(false);
		add(BorderLayout.CENTER, area);
		// /////////////////////////////////////////////////////////////////////////////////////////
		JPanel p2 = new JPanel();
		p2.setLayout(new BorderLayout());
		list = new List();
		list.add(listTitle);
		p2.add(BorderLayout.CENTER, list);
		JPanel p3 = new JPanel();
		p3.setLayout(new GridLayout(1, 2));
		bt2 = new JButton("Save");
		bt2.addActionListener(this);
		bt3 = new JButton("Message");
		bt3.addActionListener(this);
		p3.add(bt2);
		p3.add(bt3);
		p2.add(BorderLayout.SOUTH, p3);
		add(BorderLayout.EAST, p2);
		// ///////////////////////////////////////////////////////////////////////////////////////////
		JPanel p4 = new JPanel();
		tf3 = new JTextField("", 30);
		tf3.addActionListener(this);
		bt4 = new JButton("send");
		bt4.addActionListener(this);
		p4.add(tf3);
		p4.add(bt4);
		add(BorderLayout.SOUTH, p4);
		setVisible(true);
		validate();
	}

	public void run() {
		try {
			String host = tf1.getText().trim();
			int port = Integer.parseInt(tf2.getText().trim());
			connect(host, port);
			// 서버 -> 사용하실 아이디를 입력하세요.
			area.append(in.readLine());
			while (true) {
				String line = in.readLine();
				if (line == null)
					break;
				else
					routine(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}// --run

	public void routine(String line) {
		int idx = line.indexOf(ChatProtocol2.MODE);
		String cmd = line.substring(0, idx);
		String data = line.substring(idx + 1);
		if (cmd.equals(ChatProtocol2.CHATLIST)) {
			// data = aaa;bbb;ccc;홍길동;
			list.removeAll(); // 기존에 리스트 아이템 전부 삭제
			list.add(listTitle);
			StringTokenizer st = new StringTokenizer(data, ";");
			while(st.hasMoreElements()) {
				list.add(st.nextToken());
			}
		} else if (cmd.equals(ChatProtocol2.CHATALL)) {
			area.append(data + "\n");
		}

	}// --routine

	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if (obj == bt1) {// connect
			new Thread(this).start();// run메소드 호출 결과
			bt1.setEnabled(false);
			tf1.setEnabled(false);
			tf2.setEnabled(false);
			area.setText("");
		} else if (obj == bt2) {// save

		} else if (obj == bt3) {// message

		} else if (obj == bt4 || obj == tf3) {// send
			String str = tf3.getText();
			if (filterMgr(str)) {
				new MDialog(this, "경고", "입력하신 글자는 금지어입니다.");
				return;
			}
			if (!flag) /* 아이디 입력 */ {
				sendMessage(ChatProtocol2.ID + ChatProtocol2.MODE + str);
				setTitle(getTitle() + "-" + str + "님 반갑습니다.");
				area.setText("");
				tf3.setText("");
				tf3.requestFocus();
				flag = true;
			} else /* 일반 채팅 */ {
				sendMessage(ChatProtocol2.CHATALL + ChatProtocol2.MODE + str);
				tf3.setText("");
				tf3.requestFocus();
			}
		}
	}// --actionPerformed

	public void connect(String host, int port) {
		try {
			sock = new Socket(host, port);
			in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
			out = new PrintWriter(sock.getOutputStream(), true/* auto flush */);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}// --connect

	public void sendMessage(String msg) {
		out.println(msg);
	}

	public boolean filterMgr(String msg) {
		boolean flag = false;// false이면 금지어 아님
		String str[] = { "바보", "개새끼", "새끼", "자바", "java" };
		// msg : 하하 호호 히히
		StringTokenizer st = new StringTokenizer(msg);// 생략하면 구분자는 공백
		String msgs[] = new String[st.countTokens()];
		for (int i = 0; i < msgs.length; i++) {
			msgs[i] = st.nextToken();
		}
		for (int i = 0; i < str.length; i++) {
			if (flag)
				break;// 첫번째 for문 빠져나감.
			for (int j = 0; j < msgs.length; j++) {
				if (str[i].equalsIgnoreCase(msgs[j])) {
					flag = true;
					break; // 두번째 for문 빠져나감.
				} // if
			} // for2
		} // for1
		return flag;
	}

	class Message extends Frame implements ActionListener {

		Button send, close;
		TextField name;
		TextArea ta;
		String mode;// to/from
		String id;

		public Message(String mode) {
			setTitle("쪽지보내기");
			this.mode = mode;
			id = list.getSelectedItem();
			layset("");
			validate();
		}

		public Message(String mode, String id, String msg) {
			setTitle("쪽지읽기");
			this.mode = mode;
			this.id = id;
			layset(msg);
			validate();
		}

		public void layset(String msg) {
			addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					dispose();
				}
			});
			Panel p1 = new Panel();
			p1.add(new Label(mode, Label.CENTER));
			name = new TextField(id, 20);
			p1.add(name);
			add(BorderLayout.NORTH, p1);

			ta = new TextArea("");
			add(BorderLayout.CENTER, ta);
			ta.setText(msg);
			Panel p2 = new Panel();
			if (mode.equals("TO:")) {
				p2.add(send = new Button("send"));
				send.addActionListener(this);
			}
			p2.add(close = new Button("close"));
			close.addActionListener(this);
			add(BorderLayout.SOUTH, p2);

			setBounds(200, 200, 250, 250);
			setVisible(true);
		}

		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == send) {
				sendMessage(ChatProtocol2.MESSAGE + ":" + id + ";" + ta.getText());
			}
			setVisible(false);
			dispose();
		}
	}

	class MDialog extends Dialog implements ActionListener {

		Button ok;
		ChatClient2 ct2;

		public MDialog(ChatClient2 ct2, String title, String msg) {
			super(ct2, title, true);
			this.ct2 = ct2;
			//////////////////////////////////////////////////////////////////////////////////////////
			addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					dispose();
				}
			});
			/////////////////////////////////////////////////////////////////////////////////////////
			setLayout(new GridLayout(2, 1));
			Label label = new Label(msg, Label.CENTER);
			add(label);
			add(ok = new Button("확인"));
			ok.addActionListener(this);
			layset();
			setVisible(true);
			validate();
		}

		public void layset() {
			int x = ct2.getX();
			int y = ct2.getY();
			int w = ct2.getWidth();
			int h = ct2.getHeight();
			int w1 = 150;
			int h1 = 100;
			setBounds(x + w / 2 - w1 / 2, y + h / 2 - h1 / 2, 200, 100);
		}

		public void actionPerformed(ActionEvent e) {
			tf3.setText("");
			dispose();
		}
	}

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

0개의 댓글