运行结果展示
①登陆两个用户,此时还没有创建有聊天室
②创建一个聊天室
③李四聊天被骂,自己也创建一个聊天室
代码:
①登陆:
package com.ljh;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
public class AdminLogin extends JFrame {
private JFrame frame = new JFrame("登录");
private JPanel c = (JPanel) frame.getContentPane();
private JTextField username = new JTextField();
private JPasswordField password = new JPasswordField();
private JButton ok = new JButton("确定");
private JButton cancel = new JButton("取消");
public static HashMap<String,GroupList> groupListHashMap=new HashMap<String, GroupList>(); //用来存放每个用户的聊天室列表,因为需要动态加入聊天室
public AdminLogin(){
frame.setLocation(800,350);
frame.setSize(350,240);
c.setLayout(new BorderLayout());
initFrame();
frame.setVisible(true);
}
private void initFrame() {
//顶部
JPanel titlePanel = new JPanel();
titlePanel.setBackground(Color.GRAY);
titlePanel.setLayout(new FlowLayout());
titlePanel.add(new JLabel("聊天室登录"));
c.add(titlePanel,"North");
//中部表单
JPanel fieldPanel = new JPanel();
fieldPanel.setBackground(Color.lightGray);
fieldPanel.setLayout(null);
final JLabel l1 = new JLabel("用户名:");
l1.setBounds(50, 30, 50, 20);
final JLabel l2 = new JLabel("密 码:");
l2.setBounds(50, 70, 50, 20);
fieldPanel.add(l1);
fieldPanel.add(l2);
username.setBounds(110,30,120,20);
password.setBounds(110,70,120,20);
username.setText("");
password.setText("");
fieldPanel.add(username);
fieldPanel.add(password);
c.add(fieldPanel,"Center");
//底部按钮
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout());
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String clicentName=username.getText();
GroupList groupList=new GroupList(clicentName);
groupListHashMap.put(clicentName,groupList);
groupList.showRoom(); //登陆之后显示已经存在的聊天室
}
});
ok.setBackground(Color.PINK);
cancel.setBackground(Color.pink);
buttonPanel.add(cancel);
buttonPanel.add(ok);
c.add(buttonPanel,"South");
}
public static void main(String args[]){
AdminLogin login=new AdminLogin();
ChatServer r = new ChatServer();
r.start();
}
}
②聊天室列表;
package com.ljh;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
public class GroupList extends JFrame{
public static int groupNum=0;
private static final long serialVersionUID = 1L;
JFrame frame = new JFrame("聊天室列表");
JLabel showRoomNumLabel=new JLabel("num1"); //用来显示聊天室的数量
JButton createButton=new JButton("创建聊天室");
String clientName;
public GroupList(final String clientName ){
this.clientName=clientName;
createButton.setBackground(Color.pink);
frame.setTitle("聊天室列表-----用户:"+clientName);
//frame.setLayout(null);
frame.setSize(800, 500);
ImageIcon background = new ImageIcon("E:\\计算机网络\\udp_chat\\src\\main\\resources\\img\\bg.jpg");// 背景图片
JLabel label = new JLabel(background);// 把背景图片显示在一个标签里面
label.setBounds(0, 0, background.getIconWidth(),
background.getIconHeight());
JPanel jpanel = (JPanel) frame.getContentPane();
jpanel.setOpaque(false);
jpanel.setLayout(null);
frame.getLayeredPane().setLayout(null);
frame.getLayeredPane().add(label, new Integer(Integer.MIN_VALUE));
frame.setResizable(false);
frame.setVisible(true);
createButton.setBounds(350,0,100,20);
frame.add(createButton);
showRoomNumLabel.setBounds(20,3,200,30);
frame.add(showRoomNumLabel);
frame.show();
createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final createFrame create=new createFrame();
create.okCreateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(create.createGroupId.getText()!=null){
if(createRoom(create.createGroupId.getText())){
try {
new ChatClient(create.createGroupId.getText(),clientName);
Iterator iterator= AdminLogin.groupListHashMap.keySet().iterator();
while (iterator.hasNext()){ //遍历每个用户的聊天室列表
GroupList groupList=AdminLogin.groupListHashMap.get(iterator.next());
groupList.addRoom(create.createGroupId.getText()); //每个用户的聊天列表都加上新建的这个聊天列表
}
} catch (SocketException e1) {
e1.printStackTrace();
}
finally {
create.createFrame1.setVisible(false);
}
}
}
}
});
}
});
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Set<String> groups=ChatServer.groups.keySet();
Iterator<String> iterator=groups.iterator();
while(iterator.hasNext()) { //如果聊天室没人,那么该聊天室会被移除
String groupId=iterator.next();
ArrayList<ChatClient> group=ChatServer.groups.get(groupId);
if (group.size()==0){
System.out.println(groupId+"会被移除----------------");
removeRoom(groupId);
return;
}
}
dispose();
}
});
}
public void addRoom(final String groupId){ //向用户列表添加聊天室
JButton button=new JButton("<html><body>"+groupId+"<br>点击进入</body></html>");
button.setBackground(Color.lightGray);
int row=0;
int colunm=0;
if(groupNum%3==0){
colunm=3;
}else if(groupNum%3==2){
colunm=2;
}else colunm=1;
row=groupNum/3;
if(groupNum%3==0) row--;
button.setBounds(25+250*(colunm-1),(10+150)*row+30,200,150);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
new ChatClient(groupId,clientName);
} catch (SocketException e1) {
e1.printStackTrace();
}
}
}); showRoomNumLabel.setText("当前聊天室数量"+groupNum);
frame.add(button);
frame.validate(); //初始化比较晚,所以添加组件后必须要刷新才能显示
frame.repaint();
}
public boolean createRoom(String groupId){ //这个方法是创建一个不存在的聊天室
if(groupId=="")return false;
Set groupsName=ChatServer.groups.keySet();
Iterator iterator=groupsName.iterator();
while (iterator.hasNext()){
if (iterator.next().equals(groupId)){ //如果已经存在这个聊天室id了
return false;
}
}
groupNum++;
return true;
}
public boolean removeRoom(String groupId){ //删除一个聊天室
if(groupNum<=0){
return false;
}
ChatServer.groups.remove(groupId);
Iterator<String> iterator= AdminLogin.groupListHashMap.keySet().iterator();
groupNum--;
while (iterator.hasNext()){
String clientName=iterator.next();
GroupList groupList=AdminLogin.groupListHashMap.get(clientName); //获得所有的登陆用户,以便下面更改他们的聊天室显示
groupList.frame.getContentPane().removeAll();
groupList.showRoom();
groupList.frame.validate();
groupList.frame.repaint();
}
return true;
}
public void showRoom(){
if(groupNum<=0){ //如果当前没有聊天室则在相应地方显示
showRoomNumLabel.setText("当前没还有聊天室");
frame.validate();
frame.repaint();
return;
}
Set groupsName=ChatServer.groups.keySet();
int num=ChatServer.groups.size();
Iterator<String> iterator=groupsName.iterator();
for(int i=1;i<=num+1;i++) {
if (iterator.hasNext()) {
final String groupId=iterator.next();
JButton button=new JButton("<html><body>"+groupId+"<br>点击进入</body></html>");
button.setBackground(Color.lightGray);
int row=0;
int colunm=0;
if(i%3==0){
colunm=3;
}else if(i%3==2){
colunm=2;
}else colunm=1;
row=i/3;
if(i%3==0) row--;
button.setBounds(25+250*(colunm-1),(10+150)*row+30,200,150);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
new ChatClient(groupId,clientName);
} catch (SocketException e1) {
e1.printStackTrace();
}
}
});
frame.setTitle("聊天室列表-----用户:"+clientName);
showRoomNumLabel.setText("当前聊天室数量"+groupNum);
frame.add(createButton);
frame.add(showRoomNumLabel);
frame.add(button);
frame.validate(); //初始化比较晚,所以添加组件后必须要刷新才能显示
frame.repaint();
}
}
}
}
③客户端
package com.ljh;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
public class ChatClient extends JFrame {
private static final long serialVersionUID = 1L;
// 聊天室ID
private String groupID;
// 客户端用户名
public String clientName;
// 客户端套接字
private DatagramSocket msg_send;
// 服务端口
private final int PORT = 10000;
// 服务器IP地址
private InetAddress ip;
// 客户端控件
TextArea tf = new TextArea(8,55);
TextArea ta = new TextArea(15,55);
JTextArea showClient=new JTextArea(10,23);
Button send = new Button("send");
JLabel loginShow=new JLabel();
// 客户端构造器
public ChatClient(final String groupID, String clientName) throws SocketException {
super("聊天室:" + groupID + "/" + clientName);
this.clientName = clientName;
this.groupID = groupID;
ta.setBackground(Color.lightGray);
send.setBackground(Color.cyan);
Panel panel1=new Panel();
Panel panel2=new Panel();
panel1.setLayout(new FlowLayout());
panel2.add(showClient);
panel1.add(ta);
panel1.add(tf);
add("North",loginShow);
add("Center",panel1);
add("South", send);
add("East",showClient);
setSize(680, 500);
show();
// 聊天相关服务器初始化
init();
try {
// 获取输入内容
String content = tf.getText();
// 发送登陆消息
send_login(content);
// 清空聊天框
tf.setText(null);
} catch (Exception ioe) {
System.out.print(ioe.getMessage());
}
// 监听器
final ChatClient this_=this;
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
String content = tf.getText();
// 发送离线消息消息
send_go(content);
ChatServer.leaveGroup(groupID,this_); //将离开的用户从group中删除
// 清空聊天框
tf.setText(null);
} catch (Exception ioe) {
System.out.print(ioe.getMessage());
}
// 关闭消息发送服务
msg_send.close();
// 关闭客户端程序
dispose();
//System.exit(0);
}
});
}
private void init() throws SocketException {
ChatServer.logInGroup(groupID, this);
try {
msg_send = new DatagramSocket();
// 指定消息服务器
try {
ip = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e) {
System.out.println("连接错误");
}
} catch (SocketException e) {
System.out.println("连接错误");
}
}
// 消息发送按钮监听
public boolean action(Event evt, Object arg) {
if (evt.target.equals(send)) {
try {
// 获取输入内容
String content = tf.getText();
// 发送聊天消息
send_message(content);
// 清空聊天框
tf.setText(null);
} catch (Exception ioe) {
System.out.print(ioe.getMessage());
}
}
return true;
}
// 消息发送
private void send_message(String content) {
String message = messageFormat0(content);
// 将消息封装成UDP数据包
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, ip, PORT);
try {
// 通过UDP协议发送消息
msg_send.send(packet);
} catch (IOException e) {
System.out.println("IO异常..");
}
}
private void send_login(String content) {
// 消息格式化(json格式)
String message = messageFormat1(content);
// 将消息封装成UDP数据包
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, ip, PORT);
try {
msg_send.send(packet);
} catch (IOException e) {
System.out.println("IO异常..");
}
}
private void send_go(String content) {
String message = messageFormat2(content);
// 将消息封装成UDP数据包
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, ip, PORT);
try {
msg_send.send(packet);
} catch (IOException e) {
System.out.println("IO异常..");
}
}
// 消息格式化
private String messageFormat0(String content) {
StringBuffer buffer = new StringBuffer();
buffer.append("{\"isLogin\":\"").append(0).append("\",");
buffer.append("\"groupId\":").append("\"").append(groupID).append(
"\",");
buffer.append("\"userName\":\"").append(clientName).append("\",");
buffer.append("\"text\":\"").append(content).append("\"}");
return buffer.toString();
}
private String messageFormat1(String content) {
StringBuffer buffer = new StringBuffer();
buffer.append("{\"isLogin\":\"").append(1).append("\",");
buffer.append("\"groupId\":").append("\"").append(groupID).append(
"\",");
buffer.append("\"userName\":\"").append(clientName).append("\",");
buffer.append("\"text\":\"").append(content).append("\"}");
return buffer.toString();
}
private String messageFormat2(String content) {
StringBuffer buffer = new StringBuffer();
buffer.append("{\"isLogin\":\"").append(-1).append("\",");
buffer.append("\"groupId\":").append("\"").append(groupID).append(
"\",");
buffer.append("\"userName\":\"").append(clientName).append("\",");
buffer.append("\"text\":\"").append(content).append("\"}");
return buffer.toString();
}
// 从服务器获取聊天室消息
public void pushBackMessage(MessageEntity me) {
if(me.getIsLogin()==0) {
ta.append(me.getUserName() + ":" + me.getText());
ta.append("\n");
}else if(me.getIsLogin()==1){
loginShow.setText(me.getUserName()+ "进入了聊天室!");
}else loginShow.setText(me.getUserName()+"离开了聊天室!");
}
public void setShowClient(ArrayList<ChatClient> clients){
// for(ChatClient client:clients) {
// showClient.append(client.clientName+"\n");
// }
StringBuffer show=new StringBuffer();
show.append("当前聊天室人数:"+ChatServer.groups.get(groupID).size()+"\n");
for (ChatClient client:clients){
show.append(client.clientName+"\n");
}
showClient.setText(show.toString());
}
public void setShowClientNull(ArrayList<ChatClient> clients){
for(ChatClient client:clients) {
showClient.setText("");
}
}
}
④消息处理服务端:
package com.ljh;
import com.google.gson.Gson;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
public class ChatServer extends Thread{
// 端口号
private static final int PORT = 10000;
// 套接字对象
private static DatagramSocket server = null;
public static HashMap<String, ArrayList<ChatClient>> groups = new HashMap<String, ArrayList<ChatClient>>();
public ChatServer() {
try {
// 消息接受套接字对象的构造初始化
server = new DatagramSocket(PORT);
} catch (SocketException e) {
e.printStackTrace();
}
}
public static void logInGroup(String groupID, ChatClient client) throws SocketException {
// 通过聊天室ID,获取该聊天室的所有在线用户
ArrayList<ChatClient> clients = groups.get(groupID);
if (clients == null) {
clients = new ArrayList<ChatClient>();
}
// 将此次进入聊天室的用户登记
clients.add(client);
// 更新聊天室信息
groups.put(groupID, clients);
//显示在线用户
for (ChatClient chatClient:clients) {
chatClient.setShowClientNull(clients); //由于textArea的局限性,只能全部删掉再重新加入
chatClient.setShowClient(clients);
}
}
// 删除离开聊天室的用户
public static void leaveGroup(String groupID, ChatClient client) throws SocketException {
// 通过聊天室id获取所有在线用户
ArrayList<ChatClient> clients = groups.get(groupID);
if (clients == null) {
clients = new ArrayList<ChatClient>();
}
// 将离开聊天室的用户进行删除
clients.remove(client);
// 更新聊天室信息
groups.put(groupID, clients);
//显示在线用户
for (ChatClient chatClient:clients) {
chatClient.setShowClientNull(clients);
chatClient.setShowClient(clients);
}
}
// 循环接收消息
@Override
public void run() {
while (true) {
receiveMessage();
}
}
private void receiveMessage(){
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (true) {
try {
// 接受数据包
server.receive(packet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 解析数据包,获取聊天信息
String content = new String(packet.getData(), 0, packet.getLength());
// 通过第三方包解析json数据
Gson gson = new Gson();
System.out.println(content);
MessageEntity me = gson.fromJson(content, MessageEntity.class);
// 解析消息内容,通过聊天室ID,获取该聊天室的所有在线用户
ArrayList<ChatClient> clients = groups.get(me.getGroupId());
// 将接收到的消息推送回该聊天室的各个用户
for (ChatClient client : clients){
client.pushBackMessage(me);
}
}
}
}
⑤创建聊天框
package com.ljh;
import javax.swing.*;
public class createFrame extends JFrame {
JFrame createFrame1=new JFrame("创建聊天室");
JTextField createGroupId=new JTextField();
JButton okCreateButton=new JButton("ok");
public createFrame(){
createFrame1.setLayout(null);
createFrame1.setSize(260,100);
createGroupId.setBounds(20,20,100,20);
okCreateButton.setBounds(170,20,50,20);
createFrame1.add(createGroupId);
createFrame1.add(okCreateButton);
createFrame1.show();
}
}
⑥封装消息类:
package com.ljh;
public class MessageEntity {
private String groupId;
private String userName;
private String text;
private int isLogin=0;
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public int getIsLogin() {
return isLogin;
}
public void setIsLogin(int isLogin) {
this.isLogin = isLogin;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}