• 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();
    	}
    	
    }

  • 相关阅读:
    团队作业(二):项目选题
    2019-2020-2 20175312 陶光远《网络对抗技术》 Exp9 Web安全基础
    2019-2020-2 20175312 陶光远《网络对抗技术》 Exp8 Web基础
    2019-2020-2 20175312 陶光远《网络对抗技术》 Exp7 网络欺诈防范
    2019-2020-2 20175312 陶光远《网络对抗技术》 Exp6 MSF基础应用
    2019-2020-2 20175312 陶光远《网络对抗技术》 Exp5 信息搜集与漏洞扫描
    2019-2020-2 20175312 陶光远《网络对抗技术》Exp4 恶意代码分析
    2019-2020-2 20175312 陶光远《网络对抗技术》Exp3 免杀原理与实践
    2019-2020-2 20175312 陶光远《网络对抗技术》Exp2 后门原理与实践
    2019-2020-2 20175312 陶光远《网络对抗技术》Exp1 PC平台逆向破解
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5185590.html
Copyright © 2020-2023  润新知