介绍
基于JavaFx实现聊天室,消息序列化采用fastjson。有广播与单播两中发送消息的方式。
效果图
原理图
- 退出
- 发送消息
- 广播
- 登录
消息类型
主要代码
while(true)
{
byte [] buf = new byte [1027];
DatagramPacket packet = new DatagramPacket(buf, 1024);
socket.receive(packet);//接受消息
int len = packet.getLength();
String str = new String(buf, 0, len,"UTF-8");
System.out.println(str);
msg.appendText(str + "\n");//在图形界面输出接受到的消息
JSONObject jObject = JSONObject.parseObject(str);
int type = jObject.getInteger("type");//获取消息类型
if(type == MsgType.LOGIN){//若为登录消息,则将用户数加一作为用户ID
count += 1;
User u = new User(count, packet.getAddress(), packet.getPort());
login(u);//执行登录操作
}else if(type == MsgType.UNICAST){//单播消息
unicast(jObject);
}else if(type == MsgType.BROADCAST){//广播消息
broadcast(MsgType.BROADCAST, jObject, jObject.getInteger("from"));
}else if(type == MsgType.LOGOUT){//用户登出
onlineList.removeIf(i -> i.getUid().equals(jObject.getInteger("uid")));
broadcast(type, jObject, jObject.getInteger("uid"));
msg.appendText(String.format("%d离线\n", jObject.getInteger("uid")));
}
}
/*
此函数执行新用户登录的操作,即在线用户列表添加该用户,并向其他客户端广播该用户登录,给该用户客户端返回在线用户列表,参数u为新登录的用户
*/
void login(User u) throws IOException
{
List<Integer> list = new ArrayList<>();
for(User uItem : onlineList){//获取所有在线用户
list.add(uItem.getUid());
}
onlineList.add(u);//在线用户列表添加该用户
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", MsgType.ONLINE);
jsonObject.put("online", list);
jsonObject.put("uid", u.getUid());
System.out.println(jsonObject.toJSONString());
byte [] buff = jsonObject.toJSONString().getBytes("UTF-8");
DatagramPacket dPacket = new DatagramPacket(buff, buff.length, u.getHost(), u.getPort());
socket.send(dPacket);//给该客户端发送在线用户列表
JSONObject logMsg = new JSONObject();
logMsg.put("type", MsgType.LOGIN);
logMsg.put("uid", u.getUid());
broadcast(MsgType.LOGIN, logMsg, u.getUid());//向其他客户端广播该用户上线
msg.appendText(String.format("%d 登录\n", u.getUid()));
}
/*
该函数实现消息的广播,通过循环遍历除发送方外的所有在线用户并给这些用户发送消息
参数type为消息类型
参数jsonObject为要发送的JSON格式的消息
参数uid为发送方的用户,给该用户不发送消息
*/
void broadcast(Integer type, JSONObject jsonObject, Integer uid) throws IOException
{
byte [] byteMsg = jsonObject.toJSONString().getBytes("UTF-8");
for(User u : onlineList){//遍历所有在线用户
if(!u.getUid().equals(uid)){//若在线用户不是发送方则发送消息
DatagramPacket dPacket = new DatagramPacket(byteMsg, byteMsg.length, u.getHost(), u.getPort());
socket.send(dPacket);
}
}
}
/*
该部分为循环接收消息,当有消息时,判断消息类型并执行相应的操作
*/
while(true)
{
byte [] buf = new byte[1024];
DatagramPacket p = new DatagramPacket(buf, 1024);
try {
socket.receive(p);//接受数据包
String s = new String(buf, 0, p.getLength(), StandardCharsets.UTF_8);//解码
System.out.println(s);
JSONObject jsonObject = JSONObject.parseObject(s);
Integer type = jsonObject.getInteger("type");//获取消息类型
if(type.equals(MsgType.LOGIN)){//若为登录消息,则将登录的用户加入客户端在线用户列表
Platform.runLater(()->{
addUser(jsonObject.getInteger("uid"));
});
}else if(type.equals(MsgType.ONLINE)){//若为在线用户消息,则更新在线用户
JSONArray list = jsonObject.getJSONArray("online");
uid = jsonObject.getInteger("uid");
Platform.runLater(()->{
getOnlienUser(list);//该函数在线用户更新为接受到的数据包中的用户
});
}else if(type.equals(MsgType.LOGOUT)){//若为登出消息,则在在线用户里删除登出的用户
Platform.runLater(()->{
rmUser(jsonObject.getInteger("uid"));//该函数移除登出的用户
});
}else{//若为普通消息,则将其显示在文本框中
showRecMsg(jsonObject);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
资源链接
https://download.csdn.net/download/m0_47230106/87562727