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聊天 服务端篇(二)的更多相关文章

  1. Mina airQQ聊天开门见山篇(一)

    Mina airQQ聊天开门见山篇(一) 近期项目可能要用到Mina,这个礼拜就在看这个框架,所以想写个小小的聊天的demo来巩固下,打算用几篇博客来记录下相关的知识 client用的是Flex Ai ...

  2. 基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)

    1.前言 本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力. 这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用: 1)IM即时通讯 ...

  3. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

  4. 使用Apache MINA框架搭建服务端

    使用MINA框架搭建服务端步骤: 1.定义一个启动服务的类MinaServer,并实现接口ServletContextListener 2.定义一个处理业务逻辑的类MinaServerHandler, ...

  5. Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交

    今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交.虽然官网上有聊静态文件的访问的部分,但是在使用Perfect框架来访问静态文件时还是有些点需要注意的,这些关键点 ...

  6. 从零开始开发IM(即时通讯)服务端(二)

    好消息:IM1.0.0版本已经上线啦,支持特性: 私聊发送文本/文件 已发送/已送达/已读回执 支持使用ldap登录 支持接入外部的登录认证系统 提供客户端jar包,方便客户端开发 github链接: ...

  7. 通过C#实现OPC-UA服务端(二)

    前言 通过我前面的一篇文件,我们已经能够搭建一个OPC-UA服务端了,并且也拥有了一些基础功能.这一次咱们就来了解一下OPC-UA的服务注册与发现,如果对服务注册与发现这个概念不理解的朋友,可以先百度 ...

  8. 轻易实现基于linux或win运行的聊天服务端程序

    对于不了解网络编程的开发人员来说,编写一个良好的服务端通讯程序是一件比较麻烦的事情.然而通过EC这个免费组件你可以非常简单地构建一个基于linux或win部署运行的网络服务程序.这种便利性完全得益于m ...

  9. C# 服务端篇之实现RestFul Service开发(简单实用)

    一.RestFul简介 REST(Representational State Transfer 通常被翻译为“表述性状态传输”或者“表述性状态转移”)是RoyFielding提出的一个描述互联系统架 ...

随机推荐

  1. 引用 字库编码Unicode相关知识

    引用 weifeng.shen 的 字库编码Unicode相关知识 1.      各地编码 首先说明一下现在常用的一些编码方案: 1.         在中国,大陆最常用的就是GBK18030编码, ...

  2. Python用subprocess的Popen来调用系统命令

    当我们须要调用系统的命令的时候,最先考虑的os模块.用os.system()和os.popen()来进行操作.可是这两个命令过于简单,不能完毕一些复杂的操作,如给执行的命令提供输入或者读取命令的输出, ...

  3. Android利用ViewFlipper实现屏幕切换动画效果

    1.屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面:一个个性化设置页面. 2.介绍ViewFilpper类 Vie ...

  4. ThinkPHP - 登录流程

    数据库: /* Navicat MySQL Data Transfer Source Server : 本地连接 Source Server Version : 50710 Source Host : ...

  5. 第一篇:NSTread线程的创建

    #import "ViewController.h" //导入头文件 #import <pthread.h> @interfaceViewController () @ ...

  6. Android,机器狗应用

    源码如下: package com.wyl.jqr; import java.io.BufferedReader; import java.io.IOException; import java.io ...

  7. ITextSharp 初次接触

    官网:http://www.itextpdf.com/  (英文好的建议看这里) 下面我就对itextsharp做一个初步的介绍,并把最近封装的一个用于生成pdf的类库提供给需要的朋友,对于大神你可以 ...

  8. Windows Phone 8初学者开发—第15部分:在选中ListItem时播放声音

    原文 Windows Phone 8初学者开发—第15部分:在选中ListItem时播放声音 第15部分:在选中ListItem时播放声音 原文地址:  http://channel9.msdn.co ...

  9. Android学习笔记:adb 与 adb shell操作 以及中文乱码解决

    1.安装app >adb install xxx.apk 2.卸载app >adb uninstall app的包路径 如:>adb uninstall com.example.my ...

  10. csu1306: Manor

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1306 解题思路:唬人的水题,只要按照他的意思打,就能过,不过,数组最好开大点.用到优先队列,也可以 ...