小编给大家分享一下Java多线程如何实现多人聊天室功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
1.实验目的:
编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。
2.实验代码:
服务端程序代码:
ServerChar.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 Auto-generated catch block
e.printStackTrace();
}
}
}
客户端程序代码:
ClientChar.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("192.168.193.1", 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.实验截图
先开启服务端
再开启客户端
聊天过程
以上是“Java多线程如何实现多人聊天室功能”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注天达云行业资讯频道!