欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多客户端之间的通信(模拟聊天室)

程序员文章站 2024-03-22 15:05:04
...

客户端的数据包通过服务器中转,发送到另一个客户端,

		public class Message implements Serializable {
			//消息包
			private String from;//发送者
			private String to;//接收者
			private int type;//消息类型
			private String info;//消息

			public Message() {
			}

			public Message(String from, String to, int type, String info) {
				this.from = from;
				this.to = to;
				this.type = type;
				this.info = info;
			}

			public String getFrom() {
				return from;
			}

			public void setFrom(String from) {
				this.from = from;
			}

			public String getTo() {
				return to;
			}

			public void setTo(String to) {
				this.to = to;
			}

			public int getType() {
				return type;
			}

			public void setType(int type) {
				this.type = type;
			}

			public String getInfo() {
				return info;
			}

			public void setInfo(String info) {
				this.info = info;
			}

			@Override
			public String toString() {
				return "Message{" +
						"from='" + from + '\'' +
						", to='" + to + '\'' +
						", type=" + type +
						", info='" + info + '\'' +
						'}';
			}
		}

		public final class MessageType {
			public static final int TYPE_LOGIN = 0x1;//登陆消息类型
			public static final int TYPE_SEND = 0x2;//发送消息类型
		}
		
		public class Server {
			//服务器端
			public static void main(String[] args) {
				//用来保存客户端处理的线程
				Vector<UserThread> vector = new Vector<>();
				ExecutorService es = Executors.newFixedThreadPool(5);
				//创建服务器端的Socket
				try {
					ServerSocket server = new ServerSocket(8888);
					System.out.println("服务器已启动,正在等待连接");
					while (true){
						Socket socket = server.accept();
						UserThread user = new UserThread(socket,vector);
						es.execute(user);
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		//客户端处理的线程
		class UserThread implements Runnable{
			private String name;//客户端的用户名称(唯一)
			private Socket s;
			private Vector<UserThread> vector;//客户端处理线程的集合
			private ObjectInputStream ois;
			private ObjectOutputStream oos;
			private boolean flag = true;
			public UserThread(Socket s,Vector<UserThread> vector){
				this.s = s;
				this.vector = vector;
				vector.add(this);//当前线程添加到集合中
			}
			@Override
			public void run() {
				try{
					System.out.println("客户端"+s.getInetAddress().getHostAddress()+"已连接");
					ois = new ObjectInputStream(s.getInputStream());
					oos = new ObjectOutputStream(s.getOutputStream());
					while (flag){
						//读取消息对象
						Message msg = (Message) ois.readObject();
						int type = msg.getType();
						switch (type){
							case MessageType.TYPE_SEND:
								String to = msg.getTo();
								UserThread ut;
								int size = vector.size();
								for (int i = 0; i < size; i++) {
									ut = vector.get(i);
									if (to.equals(ut.name) && ut != this){
										ut.oos.writeObject(msg);
										break;
									}
								}
								break;
							case MessageType.TYPE_LOGIN:
								name = msg.getFrom();
								msg.setInfo("欢迎你:");
								oos.writeObject(msg);
								break;
						}
					}
					oos.close();
					ois.close();
				}catch (IOException | ClassNotFoundException e){
					e.printStackTrace();
				}
			}
		}
		
		public class Client {
			public static void main(String[] args) {
				ExecutorService es = Executors.newSingleThreadExecutor();
				Scanner input = new Scanner(System.in);
				try {
					Socket socket = new Socket("localhost",8888);
					System.out.println("服务器连接成功");
					ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
					ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
					//向服务器发送登陆信息
					System.out.println("请输入名称:");
					String name = input.nextLine();
					Message msg = new Message(name,null,MessageType.TYPE_LOGIN,null);
					oos.writeObject(msg);
					msg = (Message) ois.readObject();
					System.out.println(msg.getInfo()+msg.getFrom());
					//启动读取消息的线程
					es.execute(new ReadInfoThread(ois));
					//使用主线程来实现发送消息
					boolean flag = true;
					while (flag){
						msg = new Message();
						System.out.println("To:");
						msg.setTo(input.nextLine());
						msg.setFrom(name);
						msg.setType(MessageType.TYPE_SEND);
						System.out.println("Info:");
						msg.setInfo(input.nextLine());
						oos.writeObject(msg);
					}
				} catch (IOException | ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
		//读取消息
		class ReadInfoThread implements Runnable{
			private ObjectInputStream in;
			private boolean flag = true;
			public ReadInfoThread(ObjectInputStream in){
				this.in = in;
			}
			public void setFlag(boolean flag) {
				this.flag = flag;
			}

			@Override
			public void run() {
				try{
					while (flag){
						Message message = (Message) in.readObject();
						System.out.println("["+message.getFrom()+"]对我说:"+message.getInfo());
					}
					if (in != null){
						in.close();
					}
				}catch (IOException | ClassNotFoundException e){
					e.printStackTrace();
				}
			}
		}