Mina airQQ聊天 服务端篇(二)
Mina聊天服务端实现思路:在用户登录的时候。连接服务端而且验证登录用户,假设成功,则将IoSession保存到map<账号,IoSession>中,而且通知该用户的好友上线,然
后再请求好友列表;若不成功,则断开连接。
自己定义协议格式:包头+包体
包头(10字节):包头长度(short)+ 消息类型(byte)+ 内容类型(byte) + 消息命令(short)+ 包体长度(int)
包体:JSON字符串
自己定义编码解码:因为数据在网络传输过程中都是以二进制传输的,所以我们能够自己定义自己的编码解码格式。具体实现代码能够看以下的
ChatServerDecode和ChatServerEncode
数据库(chat):三张表 用户表(user)。好友表(friends),分类表(category)
- /*
- Navicat MySQL Data Transfer
- Source Server : bufoon
- Source Server Version : 50527
- Source Host : localhost:3306
- Source Database : chat
- Target Server Type : MYSQL
- Target Server Version : 50527
- File Encoding : 65001
- Date: 2014-06-29 23:30:28
- */
- SET FOREIGN_KEY_CHECKS=0;
- -- ----------------------------
- -- Table structure for category
- -- ----------------------------
- DROP TABLE IF EXISTS `category`;
- CREATE TABLE `category` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `user_id` int(11) DEFAULT NULL,
- `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
- `create_time` datetime DEFAULT NULL,
- PRIMARY KEY (`id`),
- KEY `FK_CATEGOFY_USER_ID` (`user_id`),
- CONSTRAINT `FK_CATEGOFY_USER_ID` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
- ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
- -- ----------------------------
- -- Records of category
- -- ----------------------------
- INSERT INTO `category` VALUES ('1', '1', '我的好友', '2014-06-29 19:00:25');
- INSERT INTO `category` VALUES ('3', '2', '我的好友', '2014-06-29 19:00:55');
- INSERT INTO `category` VALUES ('4', '3', '我的好友', '2014-06-29 19:01:00');
- INSERT INTO `category` VALUES ('5', '1', '同学', '2014-06-29 20:39:04');
- -- ----------------------------
- -- Table structure for friends
- -- ----------------------------
- DROP TABLE IF EXISTS `friends`;
- CREATE TABLE `friends` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `user_id` int(11) DEFAULT NULL,
- `friend_id` int(11) DEFAULT NULL,
- `category_id` int(11) DEFAULT NULL,
- `create_time` datetime DEFAULT NULL,
- PRIMARY KEY (`id`),
- KEY `FK_FRIENDS_USER_ID` (`user_id`),
- KEY `FK_FRIENDS_CATEGORY_ID` (`category_id`),
- KEY `FK_FRIENDS_FUSER_ID` (`friend_id`),
- CONSTRAINT `FK_FRIENDS_CATEGORY_ID` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE,
- CONSTRAINT `FK_FRIENDS_FUSER_ID` FOREIGN KEY (`friend_id`) REFERENCES `user` (`id`) ON DELETE CASCADE,
- CONSTRAINT `FK_FRIENDS_USER_ID` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
- ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
- -- ----------------------------
- -- Records of friends
- -- ----------------------------
- INSERT INTO `friends` VALUES ('1', '1', '2', '1', '2014-06-21 23:35:16');
- INSERT INTO `friends` VALUES ('2', '1', '3', '1', '2014-06-21 23:35:22');
- INSERT INTO `friends` VALUES ('3', '2', '1', '3', '2014-06-22 02:09:24');
- INSERT INTO `friends` VALUES ('4', '3', '1', '4', '2014-06-22 02:09:29');
- -- ----------------------------
- -- Table structure for user
- -- ----------------------------
- DROP TABLE IF EXISTS `user`;
- CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
- `user_num` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
- `password` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
- `regist_time` datetime DEFAULT NULL,
- `sex` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL,
- `signature` varchar(300) COLLATE utf8_unicode_ci DEFAULT NULL,
- `head_pic_path` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
- `is_online` varchar(1) COLLATE utf8_unicode_ci DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
- -- ----------------------------
- -- Records of user
- -- ----------------------------
- INSERT INTO `user` VALUES ('1', '张三', '12345', '12345', '2014-06-20 23:32:26', '男', null, null, '0');
- INSERT INTO `user` VALUES ('2', '李四', '123456', '123456', '2014-06-20 23:32:31', '女', null, null, '1');
- INSERT INTO `user` VALUES ('3', '王二', '1234567', '1234567', '2014-06-21 11:29:41', '男', null, null, '1');
项目文件夹结构:
须要的jar包:
ChatServer.java
- package com.bufoon.main;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
- import org.apache.mina.core.session.IdleStatus;
- import org.apache.mina.filter.codec.ProtocolCodecFilter;
- import org.apache.mina.filter.keepalive.KeepAliveFilter;
- import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
- import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
- import org.apache.mina.filter.logging.LogLevel;
- import org.apache.mina.filter.logging.LoggingFilter;
- import org.apache.mina.transport.socket.SocketAcceptor;
- import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
- import com.bufoon.codeFactory.ChatServerCodecFactory;
- import com.bufoon.handle.ChatServerHandle;
- import com.bufoon.handle.KeepAliveMessageFactoryImpl;
- import com.bufoon.handle.KeepAliveRequestTimeoutHandlerImpl;
- public class ChatServer {
- private static final int PORT = 7073;
- //30秒后超时
- private static final int IDELTIMEOUT = 30;
- //15秒发送一次心跳包
- private static final int HEARTBEATRATE = 15;
- private static SocketAcceptor acceptor;
- public static SocketAcceptor getAcceptor(){
- if(null==acceptor){
- // 创建非堵塞的server端的Socket连接
- acceptor = new NioSocketAcceptor();
- }
- return acceptor;
- }
- public static boolean serverStart() {
- DefaultIoFilterChainBuilder filterChain = getAcceptor().getFilterChain();
- // 加入编码过滤器 处理乱码、编码问题
- filterChain.addLast("codec", new ProtocolCodecFilter(new ChatServerCodecFactory()));
- LoggingFilter loggingFilter = new LoggingFilter();
- loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO);
- loggingFilter.setMessageSentLogLevel(LogLevel.INFO);
- // 加入日志过滤器
- filterChain.addLast("loger", loggingFilter);
- // 设置核心消息业务处理器
- getAcceptor().setHandler(new ChatServerHandle());
- KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl();
- KeepAliveRequestTimeoutHandler heartBeatHandler = new KeepAliveRequestTimeoutHandlerImpl();
- KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,IdleStatus.BOTH_IDLE, heartBeatHandler);
- // 是否回发
- heartBeat.setForwardEvent(true);
- // 发送频率
- heartBeat.setRequestInterval(HEARTBEATRATE);
- // getAcceptor().getFilterChain().addLast("heartbeat", heartBeat);
- getAcceptor().getSessionConfig().setBothIdleTime(30);
- // 设置session配置,30秒内无操作进入空暇状态
- getAcceptor().getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, IDELTIMEOUT);
- try {
- // 绑定端口7033
- getAcceptor().bind(new InetSocketAddress(PORT));
- return true;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return false;
- }
- public static void main(String[] args) {
- ChatServer.serverStart();
- System.out.println("服务器启动...");
- }
- }
ChatServerHandle.java
- package com.bufoon.handle;
- import java.sql.ResultSet;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import net.sf.json.JSONArray;
- import net.sf.json.JSONObject;
- import org.apache.mina.core.service.IoHandlerAdapter;
- import org.apache.mina.core.session.IdleStatus;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.example.chat.ChatProtocolHandler;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import com.bufoon.model.CategoryModel;
- import com.bufoon.model.FriendsModel;
- import com.bufoon.model.LoginModel;
- import com.bufoon.model.PackageHead;
- import com.bufoon.model.SendModel;
- import com.bufoon.model.UserModel;
- import com.bufoon.util.BaseDAO;
- import com.bufoon.util.DBUtil;
- import com.bufoon.util.MessageType;
- public class ChatServerHandle extends IoHandlerAdapter {
- private final static Logger logger = LoggerFactory.getLogger(ChatProtocolHandler.class);
- public static Map<String, IoSession> sessionMap = new HashMap<String, IoSession>();
- @Override
- public void sessionCreated(IoSession session) throws Exception {
- logger.info("创建连接");
- }
- @Override
- public void sessionOpened(IoSession session) throws Exception {
- logger.info("打开连接");
- }
- @Override
- public void sessionClosed(IoSession session) throws Exception {
- logger.info("关闭连接");
- String userNum = (String) session.getAttribute("userNum");
- String sql = "update user set is_online=1 where user_num like'" + userNum + "'";
- DBUtil.getInstance().executeUpdate(sql);
- sessionMap.remove(userNum);
- //改动下线。通知
- String userSql = "select * from user where user_num like '" + userNum + "'";
- UserModel userModel = BaseDAO.getInstance().findUserModel(userSql);
- String friendListSql = "select * from friends where user_id=" + userModel.getId();
- List<FriendsModel> list = BaseDAO.getInstance().findFriendsList(friendListSql);
- for (FriendsModel friendsModel : list) {
- String fUserSql = "select * from user where id=" + friendsModel.getFriendId();
- UserModel userModel2 = BaseDAO.getInstance().findUserModel(fUserSql);
- IoSession is = sessionMap.get(userModel2.getUserNum());
- if (is != null) {
- PackageHead ph = new PackageHead();
- Map<String, Object> object = new HashMap<String, Object>();
- object.put("userNum", userModel2.getUserNum());
- object.put("status", 1); //下线
- String content = JSONObject.fromObject(object).toString();
- ph.setPackageHeadLength(10);
- ph.setMessageCommand(MessageType.USER_ON_OFF_LINE_NOTICE);
- ph.setContentType(MessageType.CONTENT_TYPE_OBJECT);
- ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH);
- ph.setPackageBodyLength(content.getBytes().length);
- ph.setPackageBodyContent(content);
- is.write(ph);
- }
- }
- }
- @Override
- public void sessionIdle(IoSession session, IdleStatus status)
- throws Exception {
- logger.info("进入空暇");
- }
- @Override
- public void exceptionCaught(IoSession session, Throwable cause)
- throws Exception {
- logger.warn("异常.", cause);
- session.close(true);
- }
- @Override
- public void messageReceived(IoSession session, Object message)
- throws Exception {
- System.out.println(message);
- PackageHead ph = (PackageHead) message;
- System.out.println("还有没有这个session:" + sessionMap.size());
- switch (ph.getMessageCommand()) {
- case MessageType.LOGIN_VERIFY: //登录请求
- LoginModel loginModel = (LoginModel)JSONObject.toBean(JSONObject.fromObject(ph.getPackageBodyContent()), LoginModel.class);
- String username = loginModel.getUsername();
- IoSession is = sessionMap.get(username);
- Map<String, Object> map = new HashMap<String, Object>();
- if (!DBUtil.getInstance().isExit("user", "user_num", username)) {
- System.out.println("用户不存在");
- map.put("status", 1);
- map.put("info", "用户不存在");
- map.put("username", username);
- } else if (is != null && is.isConnected()) {
- System.out.println("用户已登录");
- map.put("status", 2);
- map.put("info", "用户已登录");
- map.put("username", username);
- } else if (!DBUtil.getInstance().isExit("user", new String[]{"user_num", "password"}, new Object[]{username, loginModel.getPassword()})) {
- System.out.println("用户密码错误");
- map.put("status", 3);
- map.put("info", "用户密码错误");
- map.put("username", username);
- } else if (DBUtil.getInstance().isExit("user", new String[]{"user_num", "password"}, new Object[]{username, loginModel.getPassword()})) {
- String sql = "select * from user where user_num like '" + username + "'";
- ResultSet rs = DBUtil.getInstance().executeQuery(sql);
- UserModel vo = null;
- while (rs.next()) {
- vo = new UserModel();
- vo.setId(rs.getInt("id"));
- vo.setUsername(rs.getString("name"));
- vo.setUserNum(rs.getString("user_num"));
- vo.setPassword(rs.getString("password"));
- vo.setSex(rs.getString("sex"));
- vo.setSignature(rs.getString("signature"));
- vo.setIsOnline(rs.getInt("is_online"));
- break;
- }
- if (vo != null) {
- map.put("username", vo.getUsername());
- }
- map.put("status", 0);
- map.put("info", "成功");
- map.put("userNum", username);
- map.put("userVO", vo);
- session.setAttribute("userNum", username);
- sessionMap.put(username, session);
- }
- String onLinesql = "update user set is_online=0 where user_num like'" + username + "'";
- DBUtil.getInstance().executeUpdate(onLinesql);
- String content = JSONObject.fromObject(map).toString();
- ph.setMessageCommand(MessageType.LOGIN_VERIFY_ACK);
- ph.setContentType(MessageType.CONTENT_TYPE_OBJECT);
- ph.setMessageType(MessageType.MESSAGE_TYPE_REQUEST);
- ph.setPackageBodyLength(content.getBytes().length);
- ph.setPackageBodyContent(content);
- session.write(ph);
- String friendSql = "select * from user where user_num like '" + username + "'";
- ResultSet rs1 = DBUtil.getInstance().executeQuery(friendSql);
- Map<String, Object> object = new HashMap<String, Object>();
- object.put("userNum", username);
- object.put("status", 0);
- content = JSONObject.fromObject(object).toString();
- ph.setMessageCommand(MessageType.USER_ON_OFF_LINE_NOTICE);
- ph.setContentType(MessageType.CONTENT_TYPE_OBJECT);
- ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH);
- ph.setPackageBodyLength(content.getBytes().length);
- ph.setPackageBodyContent(content);
- while (rs1.next()) {
- String sql1 = "select * from friends where user_id=" + rs1.getInt("id");
- ResultSet rs2 = DBUtil.getInstance().executeQuery(sql1);
- while(rs2.next()){
- String sql2 = "select * from user where id=" + rs2.getInt("friend_id");
- ResultSet rs3 = DBUtil.getInstance().executeQuery(sql2);
- while(rs3.next()){
- IoSession iso = sessionMap.get(rs3.getString("user_num"));
- if(iso != null){
- iso.write(ph);
- }
- }
- }
- }
- break;
- case MessageType.FRIEND_LIST: //好友列表请求
- JSONObject obj = JSONObject.fromObject(ph.getPackageBodyContent());
- String userId = obj.getString("userId");
- String friendListSql = "select * from friends where user_id=" + userId;
- List<FriendsModel> friendList = BaseDAO.getInstance().findFriendsList(friendListSql);
- String categorySql = "select * from category where user_id=" + userId;
- List<CategoryModel> categoryList = BaseDAO.getInstance().findCategoryList(categorySql);
- for (CategoryModel categoryModel : categoryList) {
- for (FriendsModel friendModel : friendList) {
- if (categoryModel.getId() == friendModel.getCategoryId()) {
- String userSql = "select * from user where id=" + friendModel.getFriendId();
- categoryModel.getList().add(BaseDAO.getInstance().findUserModel(userSql));
- }
- }
- }
- String friends = JSONArray.fromObject(categoryList).toString();
- System.out.println("frends:" + friends);
- ph.setMessageCommand(MessageType.FRIEND_LIST_ACK);
- ph.setContentType(MessageType.CONTENT_TYPE_ARRAY);
- ph.setMessageType(MessageType.MESSAGE_TYPE_REQUEST);
- ph.setPackageBodyLength(friends.getBytes().length);
- ph.setPackageBodyContent(friends);
- session.write(ph);
- break;
- case MessageType.SEND_MESSAGE: //消息发送
- SendModel sendModel = (SendModel)JSONObject.toBean(JSONObject.fromObject(ph.getPackageBodyContent()), SendModel.class);
- ph.setMessageType(MessageType.SEND_MESSAGE_ACK);
- session.write(ph);
- ph.setMessageCommand(MessageType.SEND_MESSAGE_ACK_NOTICE);
- String sendStr = JSONObject.fromObject(sendModel).toString();
- ph.setPackageBodyLength(sendStr.getBytes().length);
- ph.setPackageBodyContent(sendStr);
- ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH);
- ph.setContentType(MessageType.CONTENT_TYPE_OBJECT);
- sessionMap.get(sendModel.getReceiverNum()).write(ph);
- break;
- //查找好友
- //注冊
- //加入好友
- }
- }
- @Override
- public void messageSent(IoSession session, Object message) throws Exception {
- logger.info("发送消息: " + message);
- }
- }
ChatServerCodecFactory.java
- package com.bufoon.codeFactory;
- import java.nio.charset.Charset;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.filter.codec.ProtocolCodecFactory;
- import org.apache.mina.filter.codec.ProtocolDecoder;
- import org.apache.mina.filter.codec.ProtocolEncoder;
- public class ChatServerCodecFactory implements ProtocolCodecFactory{
- private static final Charset charset = Charset.forName("UTF-8");
- @Override
- public ProtocolEncoder getEncoder(IoSession session) throws Exception {
- return new ChatServerEncode(charset);
- }
- @Override
- public ProtocolDecoder getDecoder(IoSession session) throws Exception {
- return new ChatServerDecode(charset);
- }
- }
ChatServerDecode.java
- package com.bufoon.codeFactory;
- import java.nio.ByteOrder;
- import java.nio.charset.Charset;
- import org.apache.mina.core.buffer.IoBuffer;
- import org.apache.mina.core.session.AttributeKey;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.filter.codec.ProtocolDecoder;
- import org.apache.mina.filter.codec.ProtocolDecoderOutput;
- import com.bufoon.model.PackageHead;
- public class ChatServerDecode implements ProtocolDecoder {
- private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");
- private final Charset charset;
- private int maxPackLength = 100;
- public ChatServerDecode() {
- this(Charset.defaultCharset());
- }
- public ChatServerDecode(Charset charset) {
- this.charset = charset;
- }
- public int getMaxLineLength() {
- return maxPackLength;
- }
- public void setMaxLineLength(int maxLineLength) {
- if (maxLineLength <= 0) {
- throw new IllegalArgumentException("maxLineLength: "
- + maxLineLength);
- }
- this.maxPackLength = maxLineLength;
- }
- private ChatContext getContext(IoSession session) {
- ChatContext ctx;
- ctx = (ChatContext) session.getAttribute(CONTEXT);
- if (ctx == null) {
- ctx = new ChatContext(charset);
- session.setAttribute(CONTEXT, ctx);
- }
- return ctx;
- }
- @Override
- public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
- throws Exception {
- final int packHeadLength = 10;
- // 先获取上次的处理上下文,其中可能有未处理完的数据
- in.order(ByteOrder.LITTLE_ENDIAN);
- ChatContext ctx = getContext(session);
- // 先把当前buffer中的数据追加到Context的buffer其中
- ctx.append(in);
- // 把position指向0位置。把limit指向原来的position位置
- IoBuffer buf = ctx.getBuffer();
- buf.flip();
- // 然后按数据包的协议进行读取
- if (buf.remaining() >= packHeadLength) {
- buf.mark();
- // 读取消息头部分
- PackageHead message = new PackageHead();
- message.setPackageHeadLength(buf.getShort());
- message.setMessageType(buf.get());
- message.setContentType(buf.get());
- message.setMessageCommand(buf.getShort());
- int bodyLen = buf.getInt();
- message.setPackageBodyLength(bodyLen);
- // 读取正常的消息包。并写入输出流中,以便IoHandler进行处理
- if (bodyLen > 0 && buf.remaining() >= bodyLen) {
- message.setPackageBodyContent(buf.getString(bodyLen, charset.newDecoder()));
- } else {
- //buf.clear();
- }
- out.write(message);
- }
- if (buf.hasRemaining()) {
- // 将数据移到buffer的最前面
- IoBuffer temp = IoBuffer.allocate(maxPackLength)
- .setAutoExpand(true);
- temp.put(buf);
- temp.flip();
- buf.clear();
- buf.put(temp);
- } else {// 假设数据已经处理完成,进行清空
- buf.clear();
- }
- }
- @Override
- public void finishDecode(IoSession session, ProtocolDecoderOutput out)
- throws Exception {
- }
- @Override
- public void dispose(IoSession session) throws Exception {
- ChatContext ctx = (ChatContext) session.getAttribute(CONTEXT);
- if (ctx != null) {
- session.removeAttribute(CONTEXT);
- }
- }
- }
ChatServerEncode.java
- package com.bufoon.codeFactory;
- import java.nio.ByteOrder;
- import java.nio.charset.Charset;
- import org.apache.mina.core.buffer.IoBuffer;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
- import org.apache.mina.filter.codec.ProtocolEncoderOutput;
- import com.bufoon.model.PackageHead;
- public class ChatServerEncode extends ProtocolEncoderAdapter {
- private Charset charset = null;
- public ChatServerEncode(Charset charset) {
- this.charset = charset;
- }
- @Override
- public void encode(IoSession session, Object message,
- ProtocolEncoderOutput out) throws Exception {
- if (message instanceof PackageHead) {
- PackageHead ph = (PackageHead) message;
- IoBuffer buf = IoBuffer.allocate(ph.getPackageHeadLength() + ph.getPackageBodyLength());
- buf.order(ByteOrder.LITTLE_ENDIAN);
- //buf.setAutoExpand(true);
- buf.putShort((short) ph.getPackageHeadLength());
- buf.put((byte) ph.getMessageType());
- buf.put((byte) ph.getContentType());
- buf.putShort((short) ph.getMessageCommand());
- buf.putInt((int) ph.getPackageBodyLength());
- if (ph.getPackageBodyLength() > 0) {
- buf.putString(ph.getPackageBodyContent(), charset.newEncoder());
- }
- buf.flip();
- out.write(buf);
- out.flush();
- buf.free();
- }
- }
- }
ChatContext.java
- package com.bufoon.codeFactory;
- import java.nio.ByteOrder;
- import java.nio.charset.Charset;
- import java.nio.charset.CharsetDecoder;
- import org.apache.mina.core.buffer.IoBuffer;
- public class ChatContext {
- private final CharsetDecoder decoder;
- private IoBuffer buf;
- private int matchCount = 0;
- private int overflowPosition = 0;
- public ChatContext(Charset charset) {
- decoder = charset.newDecoder();
- buf = IoBuffer.allocate(80).setAutoExpand(true);
- buf.order(ByteOrder.LITTLE_ENDIAN);
- }
- public CharsetDecoder getDecoder() {
- return decoder;
- }
- public IoBuffer getBuffer() {
- return buf;
- }
- public int getOverflowPosition() {
- return overflowPosition;
- }
- public int getMatchCount() {
- return matchCount;
- }
- public void setMatchCount(int matchCount) {
- this.matchCount = matchCount;
- }
- public void reset() {
- overflowPosition = 0;
- matchCount = 0;
- decoder.reset();
- }
- public void append(IoBuffer in) {
- getBuffer().put(in);
- }
- }
MessageType.java
- package com.bufoon.util;
- public class MessageType {
- /**登录验证请求消息类型**/
- public final static int LOGIN_VERIFY = 0x0000;
- /**登录验证响应消息类型**/
- public final static int LOGIN_VERIFY_ACK = 0x0001;
- /**心跳请求消息类型**/
- public final static int HEART_BEAT = 0x0002;
- /**心跳响应消息类型**/
- public final static int HEART_BEAT_ACK = 0x0003;
- /**好友列表请求消息类型**/
- public final static int FRIEND_LIST = 0x0004;
- /**好友列表响应消息类型**/
- public final static int FRIEND_LIST_ACK = 0x0005;
- /**发送消息请求**/
- public final static int SEND_MESSAGE = 0x0006;
- /**发送消息响应**/
- public final static int SEND_MESSAGE_ACK = 0x0007;
- /**发送消息通知响应**/
- public final static int SEND_MESSAGE_ACK_NOTICE = 0x1000;
- /**通知用户上下线**/
- public final static int USER_ON_OFF_LINE_NOTICE = 0X1001;
- /**包头大小**/
- public final static int HEAD_LENGTH = 10;
- /**返回的消息类型 0服务端推送**/
- public final static int MESSAGE_TYPE_PUSH = 0;
- /**返回的消息类型 1请求响应**/
- public final static int MESSAGE_TYPE_REQUEST = 1;
- /**返回的内容类型 0 JsonObject**/
- public final static int CONTENT_TYPE_OBJECT = 0;
- /**返回的内容类型 1 JsonArray**/
- public final static int CONTENT_TYPE_ARRAY = 1;
- }
DBUtil.java
- package com.bufoon.util;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- /**
- * 数据库 连接类
- * @author AllenYe
- *
- */
- public class DBUtil
- {
- private static final DBUtil uniqueInstance = new DBUtil();
- private DBUtil(){
- //载入mysql-jdbc桥接器:
- try{
- Class.forName("com.mysql.jdbc.Driver");
- }catch(ClassNotFoundException e){}
- }
- public static DBUtil getInstance() {
- return uniqueInstance;
- }
- //公共的connection
- private Connection conn=null;
- private Connection getConnection() throws Exception
- {
- if(conn == null)
- {
- //设置connection的url,账号,password
- conn=DriverManager.getConnection(
- "jdbc:mysql://localhost:3306/chat?
- useUnicode=true&characterEncoding=UTF-8"
- ,"root"
- ,"root");
- }
- return conn;
- }
- public ResultSet executeQuery(String sql)
- {
- try
- {
- Statement statement = getConnection().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
- ResultSet rs = statement.executeQuery(sql);
- return rs;
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- public int executeUpdate(String sql)
- {
- try
- {
- PreparedStatement statement = getConnection().prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
- int result = statement.executeUpdate();
- return result;
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return -1;
- }
- public boolean isExit(String table, String column, String value){
- String sql = "select * from " + table + " where " + column + " like '" + value + "'";
- ResultSet rs = this.executeQuery(sql);
- boolean flag = false;
- try {
- while (rs.next()) {
- flag = true;
- break;
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return flag;
- }
- public boolean isExit(String table, String column[], Object value[]){
- StringBuffer sb = new StringBuffer("select * from " + table + " where 1=1");
- for(int i = 0; i < column.length; i++){
- sb.append(" and " + column[i] + " like '" + value[i] + "'");
- }
- ResultSet rs = this.executeQuery(sb.toString());
- boolean flag = false;
- try {
- while (rs.next()) {
- flag = true;
- break;
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return flag;
- }
- }
BaseDAO.java
- package com.bufoon.util;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- import com.bufoon.model.CategoryModel;
- import com.bufoon.model.FriendsModel;
- import com.bufoon.model.UserModel;
- public class BaseDAO {
- private static final BaseDAO uniqueInstance = new BaseDAO();
- private BaseDAO(){
- }
- public static BaseDAO getInstance() {
- return uniqueInstance;
- }
- public UserModel findUserModel(String sql){
- UserModel vo = null;
- try {
- ResultSet rs = DBUtil.getInstance().executeQuery(sql);
- while(rs.next()){
- vo = new UserModel();
- vo.setId(rs.getInt("id"));
- vo.setUsername(rs.getString("name"));
- vo.setUserNum(rs.getString("user_num"));
- vo.setPassword(rs.getString("password"));
- vo.setIsOnline(rs.getInt("is_online"));
- vo.setSignature(rs.getString("signature"));
- vo.setSex(rs.getString("sex"));
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return vo;
- }
- public List<FriendsModel> findFriendsList(String sql){
- List<FriendsModel> list = new ArrayList<FriendsModel>();
- try {
- ResultSet rs = DBUtil.getInstance().executeQuery(sql);
- FriendsModel vo = null;
- while(rs.next()){
- vo = new FriendsModel();
- vo.setId(rs.getInt("id"));
- vo.setUserId(rs.getInt("user_id"));
- vo.setFriendId(rs.getInt("friend_id"));
- vo.setCategoryId(rs.getInt("category_id"));
- vo.setCreateTime(Util.formatTime(rs.getDate("create_time")));
- list.add(vo);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return list;
- }
- public List<CategoryModel> findCategoryList(String sql){
- List<CategoryModel> list = new ArrayList<CategoryModel>();
- CategoryModel vo = null;
- ResultSet rs = DBUtil.getInstance().executeQuery(sql);
- try {
- while(rs.next()){
- vo = new CategoryModel();
- vo.setId(rs.getInt("id"));
- vo.setUserId(rs.getInt("user_id"));
- vo.setName(rs.getString("name"));
- vo.setCreateTime(Util.formatTime(rs.getDate("create_time")));
- list.add(vo);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return list;
- }
- }
PackageHead.java
- package com.bufoon.model;
- import java.io.Serializable;
- public class PackageHead implements Serializable {
- private static final long serialVersionUID = 3965541808116510722L;
- private int id; //id
- private int packageHeadLength; //包头长度 short 2个字节 长度为10
- private int messageType; //消息类型 byte 1字节
- private int contentType; //内容类型 1字节
- private int messageCommand; //消息命令 short 2字节
- private int packageBodyLength; //包体长度 消息int 4字节
- private String packageBodyContent; //包体内容 大小 为packageBodyLength
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getPackageHeadLength() {
- return packageHeadLength;
- }
- public void setPackageHeadLength(int packageHeadLength) {
- this.packageHeadLength = packageHeadLength;
- }
- public int getMessageType() {
- return messageType;
- }
- public void setMessageType(int messageType) {
- this.messageType = messageType;
- }
- public int getContentType() {
- return contentType;
- }
- public void setContentType(int contentType) {
- this.contentType = contentType;
- }
- public int getMessageCommand() {
- return messageCommand;
- }
- public void setMessageCommand(int messageCommand) {
- this.messageCommand = messageCommand;
- }
- public int getPackageBodyLength() {
- return packageBodyLength;
- }
- public void setPackageBodyLength(int packageBodyLength) {
- this.packageBodyLength = packageBodyLength;
- }
- public String getPackageBodyContent() {
- return packageBodyContent;
- }
- public void setPackageBodyContent(String packageBodyContent) {
- this.packageBodyContent = packageBodyContent;
- }
- @Override
- public String toString() {
- return "Messeage is: command=" + getMessageCommand() + ", type=" + getMessageType() + ", contentLength=" + getPackageBodyLength() + ", content=" + getPackageBodyContent();
- }
- }
Mina airQQ聊天 服务端篇(二)的更多相关文章
- Mina airQQ聊天开门见山篇(一)
Mina airQQ聊天开门见山篇(一) 近期项目可能要用到Mina,这个礼拜就在看这个框架,所以想写个小小的聊天的demo来巩固下,打算用几篇博客来记录下相关的知识 client用的是Flex Ai ...
- 基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)
1.前言 本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力. 这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用: 1)IM即时通讯 ...
- Netty入门之客户端与服务端通信(二)
Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
- 使用Apache MINA框架搭建服务端
使用MINA框架搭建服务端步骤: 1.定义一个启动服务的类MinaServer,并实现接口ServletContextListener 2.定义一个处理业务逻辑的类MinaServerHandler, ...
- Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交
今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交.虽然官网上有聊静态文件的访问的部分,但是在使用Perfect框架来访问静态文件时还是有些点需要注意的,这些关键点 ...
- 从零开始开发IM(即时通讯)服务端(二)
好消息:IM1.0.0版本已经上线啦,支持特性: 私聊发送文本/文件 已发送/已送达/已读回执 支持使用ldap登录 支持接入外部的登录认证系统 提供客户端jar包,方便客户端开发 github链接: ...
- 通过C#实现OPC-UA服务端(二)
前言 通过我前面的一篇文件,我们已经能够搭建一个OPC-UA服务端了,并且也拥有了一些基础功能.这一次咱们就来了解一下OPC-UA的服务注册与发现,如果对服务注册与发现这个概念不理解的朋友,可以先百度 ...
- 轻易实现基于linux或win运行的聊天服务端程序
对于不了解网络编程的开发人员来说,编写一个良好的服务端通讯程序是一件比较麻烦的事情.然而通过EC这个免费组件你可以非常简单地构建一个基于linux或win部署运行的网络服务程序.这种便利性完全得益于m ...
- C# 服务端篇之实现RestFul Service开发(简单实用)
一.RestFul简介 REST(Representational State Transfer 通常被翻译为“表述性状态传输”或者“表述性状态转移”)是RoyFielding提出的一个描述互联系统架 ...
随机推荐
- 结构体struct和联合体union以及enum枚举体5的区别
下面来自wikipedia: In computer science, a union is a value that may have any of several representations ...
- lines(最大区间和)
lines Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- Zend Studio 10.6.0汉化教程(图文)
来源于:http://www.pw88.com/teach/bangong/32.html 此汉化方法适用于所有的zend studio版本.整个汉化思路是:在线或者离线官方下载汉化包,本地安装即 ...
- 异常语句:try(尝试)-catch(抓取)-finally 跳转语句:break
跳转语句: 1.break:跳出的意思,如果在循环语句中使用则是跳出循环2.default,--默认语句通常与 switch case 配合使用3.continue--跳过一个,继续下一个继续retu ...
- java笔记之数据类型
java中一句连续的字符不能分开在两行中书写,如国太长可用“+”将这两个字符串连起来 文档注释是以“/**”开头,并在注释内容末尾以“*/”结束. 文档注释是对代码的解释说明,可以使用javadoc命 ...
- c++设置输出精度
float类型的精度6-7位,double类型的变量15-16位,但是float占四个字节,double占八个字节, 但能用float类型不要用double因为double占的字节数多,而且运算速度要 ...
- Ubuntu网络频繁掉线解决方案
年底了,实验室终于给配了个电脑(Ubuntu系统),博主欣喜若狂啊,然而装好后发现无线网频繁掉线,重启网络后能正常上网2~3分钟然后又掉线,再重启又能上网2~3分钟然后再掉线,博主那个不爽啊,于是各种 ...
- ASP.NET MVC 5 学习教程:添加模型
原文 ASP.NET MVC 5 学习教程:添加模型 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控 ...
- java 访问 mysql 数据库的字符集设置
mysql是在linux下,java代码通过jdbc访问总是中文乱码.做过如下尝试: 1)修改 mysql的 my.cnf文件,设置 default-character-set等参数 2) 利用alt ...
- hbase安装配置(整合到hadoop)
hbase安装配置(整合到hadoop) 如果想详细了解hbase的安装:http://abloz.com/hbase/book.html 和官网http://hbase.apache.org/ 1. ...