package com.bobo.handler;
import com.alibaba.fastjson.JSONObject;
import com.bobo.constant.CommonConstant;
import com.bobo.entity.ChatMsg;
import com.bobo.entity.FriendMsg;
import com.bobo.io.ChatBufferReader;
import com.bobo.io.ChatMsgWrapper;
import com.bobo.ui.MainUI;
import javax.swing.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author bobo
* 客户端IO处理器
*/
public class IOHandler {
private static IOHandler ioHandler = new IOHandler();
private IOHandler(){}
public static IOHandler getHandler(){
return ioHandler;
}
// 存储好友的数据
private Map<String,FriendMsg> friendsData = new LinkedHashMap<>();
// 当前客户端的ID
private String selfId;
// 当前客户端的SocketChannel
private SocketChannel socketChannel;
// 读缓冲,以\n为分隔符读取消息,用于解决TCP粘包拆包问题
private ChatBufferReader chatBufferReader = new ChatBufferReader();
// 给消息的最后添加一个分隔符\n
private ChatMsgWrapper chatMsgWrapper = new ChatMsgWrapper();
public void doConnect(MainUI mainUI) throws IOException {
Selector selector = Selector.open();
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
// 获取服务端ip:port
try {
String[] arr = mainUI.getServer().getText().split(":");
if(arr.length != 2){
throw new RuntimeException("服务端地址格式错误");
}
socketChannel.connect(new InetSocketAddress(arr[0], Integer.valueOf(arr[1])));
} catch (Exception e) {
e.printStackTrace();
UIHandler.alert(mainUI,e.getMessage(),"提示",JOptionPane.ERROR_MESSAGE);
return;
}
socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ, ByteBuffer.allocate(CommonConstant.BUFFER_SIZE));
for (;;){
int num = selector.select();
if(num <= 0){
continue;
}
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
if(key.isConnectable()){
while(!socketChannel.finishConnect()){
UIHandler.setText(mainUI.getBottom(),"客户端连接中...");
}
selfId = socketChannel.getLocalAddress().toString().substring(1);
// 连接成功后,渲染界面
UIHandler.setText(mainUI.getBottom(),"已成功连接服务器");
UIHandler.alert(mainUI,"成功连接服务器","提示",JOptionPane.INFORMATION_MESSAGE);
UIHandler.append(mainUI.getGroupArea(),"成功连接服务器,您现在可以发送群聊消息");
UIHandler.setText(mainUI.getId(),selfId);
UIHandler.setVisible(mainUI.getConnect(),false);
UIHandler.setEditable(mainUI.getServer(),false);
}else if (key.isReadable()){
// 缓冲读,以\n为分隔符读取消息,可解决TCP粘包拆包问题
String msg = chatBufferReader.readMsg(key);
ChatMsg chatMsg = JSONObject.parseObject(msg, ChatMsg.class);
if(CommonConstant.MSG_TYPE_SYNC_TO_NEW_CLIENT == chatMsg.getType()){
// 新客户端(自己)上线,获取服务端发过来的所有好友信息
Map<String,String> map = JSONObject.parseObject(chatMsg.getMsg(), Map.class);
map.forEach((subject,name)->{
// 初始化FriendMsg
friendsData.put(subject,new FriendMsg(subject,name,0,new ArrayList()));
});
// 重新加载好友列表
UIHandler.reloadFriends(mainUI);
}else if(CommonConstant.MSG_TYPE_NOTICE_HAS_NEW_CLIENT == chatMsg.getType()){
// 有新的好友上线
UIHandler.setText(mainUI.getBottom(),String.format("有新的好友[%s]已上线",chatMsg.getMsg()));
// 初始化FriendMsg
friendsData.put(chatMsg.getMsg(),new FriendMsg(chatMsg.getMsg(),"",0,new ArrayList()));
// 重新加载好友列表
UIHandler.reloadFriends(mainUI);
}else if(CommonConstant.MSG_TYPE_NOTICE_OTHER_CLIENT_MODIFY_NAME == chatMsg.getType()){
// 好友修改了昵称
UIHandler.setText(mainUI.getBottom(),
String.format("好友[%s]修改了昵称[%s]",chatMsg.getSubject(),chatMsg.getMsg()));
// 修改FriendMsg
friendsData.get(chatMsg.getSubject()).setName(chatMsg.getMsg());
// 重新加载好友列表
UIHandler.reloadFriends(mainUI);
// 如果正在与该好友聊天,则更新私聊标题
UIHandler.updatePrivateTitle(mainUI,chatMsg.getSubject(),false);
}else if(CommonConstant.MSG_TYPE_RECV_GROUP == chatMsg.getType()){
// 接收群聊消息
UIHandler.append(mainUI.getGroupArea(),UIHandler.buildSessionMsg(chatMsg.getSubject(),chatMsg.getMsg()));
}else if(CommonConstant.MSG_TYPE_RECV_PRIVATE == chatMsg.getType()){
// 接收私聊消息
FriendMsg friendMsg = friendsData.get(chatMsg.getSubject());
// 将消息记录到friendMsg的msgList中
friendMsg.getMsgList().add(UIHandler.buildSessionMsg(chatMsg.getSubject(),chatMsg.getMsg()));
if(mainUI.getPrivateTitle().getText().contains(chatMsg.getSubject())){
// 当前正在与该好友聊天,则还要将消息追加到私聊窗口
UIHandler.append(mainUI.getPrivateArea(),UIHandler.buildSessionMsg(chatMsg.getSubject(),chatMsg.getMsg()));
}else{
// 当前没有在于该好友聊天,则未读消息个数加1
friendMsg.setUnreadCount(friendMsg.getUnreadCount()+1);
// 底部通知栏添加通知
UIHandler.setText(mainUI.getBottom(),UIHandler.buildSessionMsg(chatMsg.getSubject(),"发来了一条新消息"));
// 重新加载好友列表
UIHandler.reloadFriends(mainUI);
}
}else if(CommonConstant.MSG_TYPE_NOTICE_OTHER_CLIENT_OFFLINE == chatMsg.getType()){
// 好友下线,底部通知栏添加通知
UIHandler.setText(mainUI.getBottom(),UIHandler.buildSessionMsg(chatMsg.getSubject(),"下线"));
// 如果正在与该好友聊天,则更新私聊标题
UIHandler.updatePrivateTitle(mainUI,chatMsg.getSubject(),true);
// 移除
friendsData.remove(chatMsg.getSubject());
// 重新加载好友列表
UIHandler.reloadFriends(mainUI);
}
}
// 最后移除此次发生处理的selectionKey,防止事件重复处理
iterator.remove();
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源详情
资源评论
资源推荐
收起资源包目录
CS模式聊天程序代码.zip (16个子文件)
nio-chat-server
pom.xml 1KB
src
main
java
com
bobo
handler
ServiceHandler.java 8KB
ChatServerBootstrap.java 303B
nio-chat-common
pom.xml 1002B
src
main
java
com
bobo
constant
CommonConstant.java 1005B
io
ChatBufferReader.java 2KB
ChatMsgWrapper.java 452B
entity
ChatMsg.java 779B
nio-chat-client
pom.xml 1KB
src
main
resources
trumpet.jpeg 18KB
java
com
bobo
handler
IOHandler.java 8KB
EventHandler.java 6KB
UIHandler.java 2KB
ChatClientBootstrap.java 322B
ui
MainUI.java 4KB
entity
FriendMsg.java 1KB
共 16 条
- 1
波波老师
- 粉丝: 3752
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0