Java综合应用实验-多人聊天室(多线程实现)

Java综合应用实验-多人聊天室(多线程实现)

1.实验目的:
编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。
2.实验代码:
服务端程序代码:
ServerChat.java

package works;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ServerChat {

	//定义Map集合用于存储用户的Socket以及用户的名字   key:Socket    Value:用户名
	public final static Map<Socket,String> socketsMaps = Collections.synchronizedMap(new HashMap<Socket,String>());
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			// 创建服务端套接字
			ServerSocket serverSocket = new ServerSocket(9999); 
System.out.println("------服务端暴露-------");
			while (true) {
				// 监听客户端套接字,若有客户端连接,则代码不会往下执行,否则会堵塞在此处。
				Socket socket = serverSocket.accept();

				// 开启线程,用于读取客户端发送的信息,并转发给每一个客户端
				new ThreadServer(socket).start();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

class ThreadServer extends Thread {
	private Socket socket;
	ThreadServer(){};
	ThreadServer(Socket socket)
	{
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			while(true)
			{
				DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
				String data = dataInputStream.readUTF();
				
				if(data.startsWith("①②③④")&&data.endsWith("①②③④"))
				{
					//发送过来的是用户名
					//将Socket以及用户名字都存放在Map集合中
					ServerChat.socketsMaps.put(socket, data.replace("①②③④",""));
					//获取所有的key(Socket),将所有用户的名字发送至客户端
					Set<Socket> sockets = ServerChat.socketsMaps.keySet();
					//获取所有的用户的名字,将这些名字拼装成一个字符串
					Collection<String> names = ServerChat.socketsMaps.values();
					StringBuffer sbf = new StringBuffer();
					for(String userName :names)
					{
						sbf.append(userName).append(",");
					}
					System.out.println("sbf:"+sbf.toString());
					for(Socket soc:sockets)
					{
						DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream());
						dataOutputStream.writeUTF("①②③④"+sbf.toString()+"①②③④");
						dataOutputStream.flush();
					}
				}
				else{
					//发送过来的是聊天信息
					//获取所有的key(Socket),将所有用户的名字发送至客户端
					Set<Socket> sockets = ServerChat.socketsMaps.keySet();
					//將聊天信息广播出去
					for(Socket soc:sockets)
					{
						DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream());
						dataOutputStream.writeUTF("[ "+ServerChat.socketsMaps.get(socket)+" ]说:"+data);
						dataOutputStream.flush();
					}
					
					
				}
				
				
				
			}
		} catch (IOException e) {
			// TODO 更新同步ServerChat.socketsMaps,用户列表。
			e.printStackTrace();
		}
	}
}

客户端程序代码:
ClientChat.java

package works;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ClientChat {

	private JFrame mainWin = new JFrame("聊天窗口");

	// 消息展示框
	private JTextArea displayTa = new JTextArea(14, 40);
	// 在线用户名称展示框
	private DefaultListModel<String> userListModel = new DefaultListModel<>();
	private JList<String> userList = new JList<>(userListModel);
	// 消息发送框
	private JTextArea inputTF = new JTextArea(4, 40);
	// 消息按钮
	private JButton sendBn = new JButton("发送");
	// 用户记录当前聊天用户名
	private String curUser;

	public static void main(String[] args) {
		new ClientChat().init();
	}

	private void init() {
		try {
			// 通过弹出对话框获取用户输入的用户名
			String userName = JOptionPane.showInputDialog(mainWin, "请输入您的用户名:");
			// 把用户输入的用户名,赋给curUser
			curUser = userName;
			mainWin.setTitle(curUser + "的聊天窗口");

			// 创建套接字
			Socket socket = new Socket("localhost", 9999);
			// 向服务器声明
			DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
			//发送用户名到服务端
			dataOutputStream.writeUTF("①②③④"+userName+"①②③④");
			dataOutputStream.flush();

			// 开启线程,用于读取服务器发送的信息
			new ThreadClient(socket, this).start();

			JPanel bottomPanel = new JPanel();

			// 将消息框和按钮添加到窗口的底端
			mainWin.add(bottomPanel, BorderLayout.SOUTH);
			bottomPanel.add(inputTF);
			bottomPanel.add(sendBn);

			ActionListener listener = new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					// 获取用户发送的消息
					String message = inputTF.getText();
					sendSms(message,socket);
				}
			};
			// 给发送消息按钮绑定点击事件监听器
			sendBn.addActionListener(listener);

			JPanel centerPanel = new JPanel();

			// 将展示消息区centerPanel添加到窗口的中间
			mainWin.add(centerPanel);
			// 让展示消息区可以滚动
			centerPanel.add(new JScrollPane(displayTa));
			displayTa.setEditable(false);
			// 用户列表和是否私聊放到窗口的最右边
			Box rightBox = new Box(BoxLayout.Y_AXIS);
			userList.setFixedCellWidth(60);
			userList.setVisibleRowCount(13);
			rightBox.add(new JLabel("用户列表:"));
			rightBox.add(new JScrollPane(userList));

			centerPanel.add(rightBox);

			// 关闭窗口退出当前程序
			mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			mainWin.pack(); // swing加上这句就可以拥有关闭窗口的功能
			mainWin.setVisible(true);

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
		//点击发送后将消息发送到服务器
		protected void sendSms(String sms, Socket socket) {
			try {
				//发送聊天消息到服务端
				DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
				dataOutputStream.writeUTF(sms);
				dataOutputStream.flush();	
				 
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}

		public DefaultListModel<String> getUserListModel() {
			return userListModel;
		}

		public JTextArea getDisplayTa() {
			return displayTa;
		}
		public JTextArea getInputTF()
		{
			return inputTF;
		}
}

// 定义线程类,用来读取服务器发送的信息
class ThreadClient extends Thread {
	private Socket socket;
	private ClientChat clientChat;

	ThreadClient() {
	}

	ThreadClient(Socket socket, ClientChat clientChat) {
		this.socket = socket;
		this.clientChat = clientChat;
	}

	@Override
	public void run() {

		try {
			while (true) {
				DataInputStream DataInputStream = new DataInputStream(socket.getInputStream());
				String message = DataInputStream.readUTF();

				if(message.startsWith("①②③④")&&message.endsWith("①②③④"))
				{
					//说明信息是用户名
					String[] names = message.replace("①②③④","").split(",");
					// 将用户列表先清空
					clientChat.getUserListModel().clear();
					for (int i = 0; i < names.length; ++i) {
						clientChat.getUserListModel().addElement(names[i]);
					}
				}
				else
				{
					//说明是聊天信息,将聊天信息放在displayTa中
					clientChat.getInputTF().setText("");
					clientChat.getDisplayTa().append(message+"\t\n");
				}

				
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
}

3.实验截图
先开启服务端
在这里插入图片描述
再开启客户端
在这里插入图片描述
聊天过程
在这里插入图片描述
4.更新
以面向对象方式重构了一下,代码地址:https://github.com/CHANGEA-code/ChatDemo

  • 15
    点赞
  • 167
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
好的,以下是一个简单的Java聊天室实验代码,供参考: 服务器端代码: ```java import java.io.*; import java.net.*; public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(7777); System.out.println("服务器已启动,等待客户端连接..."); while (true) { Socket socket = serverSocket.accept(); System.out.println("客户端已连接,IP地址为:" + socket.getInetAddress().getHostAddress()); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String message = null; while ((message = bufferedReader.readLine()) != null) { System.out.println("客户端说:" + message); } bufferedReader.close(); socket.close(); } } } ``` 客户端代码: ```java import java.io.*; import java.net.*; public class Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 7777); System.out.println("已连接服务器..."); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String message = null; while ((message = bufferedReader.readLine()) != null) { bufferedWriter.write(message); bufferedWriter.newLine(); bufferedWriter.flush(); if ("bye".equals(message)) { break; } } bufferedReader.close(); bufferedWriter.close(); socket.close(); } } ``` 这个聊天室实验比较简单,只能实现客户端向服务器发送消息,服务器接收消息并输出。如果需要更高级的聊天室功能,需要在代码中进行更多的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值