mina的编码和解码以及断包的处理,发送自己定义协议,仿qq聊天,发送xml或json
近期一段时间以来,mina非常火,和移动开发一样。异常的火爆。前面写了几篇移动开发的文章,都还不错。你们的鼓舞就是我最大的动力。好了,废话少说。我们来看下tcp通讯吧。
tcp通讯对于java来说是非常easy的。就是socket,也就是大家常说的套接字。大家不要把它看的非常难。
说白了tcp通讯事实上就是数据流的读写。一条输入流,一条输出流。分别复杂发消息和接收消息。
明确了这些,ok。我们来看看我写的样例吧。
先看服务器端的測试类的源代码:
package com.minaqq.test; import com.minaqq.server.ServerMsgProtocol;
import com.minaqq.worker.ServerSendMsgThread; public class MsgServerTest {
public static void main(String[] args) {
if(ServerMsgProtocol.serverStart()){
System.out.println("服务器启动成功......");
ServerSendMsgThread ssmt=new ServerSendMsgThread();
ssmt.start();
System.out.println("工作线程启动成功......");
}
}
}
服务端连接代码:
package com.minaqq.server; 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.minaqq.protocol.MsgProtocol; /**
* @see server启动类,字符串消息測试类
* @author Herman.Xiong
* @date 2013年12月6日 09:23:31
* @file MinaServer.java
* @package com.minaqq.server
* @project MINA_QQ
* @version 1.0
* @since jdk1.6,mina 2.0
*/
public class ServerMsgProtocol { //30秒后超时
private static final int IDELTIMEOUT = 30;
//15秒发送一次心跳包
private static final int HEARTBEATRATE = 15; private static SocketAcceptor acceptor; private ServerMsgProtocol() {} 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 MsgProtocol()));
LoggingFilter loggingFilter = new LoggingFilter();
loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO);
loggingFilter.setMessageSentLogLevel(LogLevel.INFO);
// 加入日志过滤器
filterChain.addLast("loger", loggingFilter);
// 设置核心消息业务处理器
getAcceptor().setHandler(new ServerMessageHandler());
//KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl();
//KeepAliveRequestTimeoutHandler heartBeatHandler = new KeepAliveRequestTimeoutHandlerImpl();
//KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,IdleStatus.BOTH_IDLE, heartBeatHandler);
// 是否回发
//heartBeat.setForwardEvent(false);
// 发送频率
//heartBeat.setRequestInterval(HEARTBEATRATE);
//getAcceptor().getFilterChain().addLast("heartbeat", heartBeat);
getAcceptor().getSessionConfig().setReceiveBufferSize(2048*5000);//接收缓冲区1M
getAcceptor().getSessionConfig().setBothIdleTime(30);
//getAcceptor().getSessionConfig().setKeepAlive(true);
// 设置session配置,30秒内无操作进入空暇状态
getAcceptor().getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, IDELTIMEOUT);
try {
// 绑定端口3456
getAcceptor().bind(new InetSocketAddress(8888));
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
} }
server的消息处理:
package com.minaqq.server; import java.text.SimpleDateFormat;
import java.util.Date; import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession; import com.minaqq.domain.MsgPack;
/**
* @see 处理server端消息
* @author Herman.Xiong
* @date 2012-6-26 下午01:12:34
* @file ServerMessageHandler.java
* @package com.minaqq.server
* @project MINA_QQ
* @version 1.0
* @since jdk1.6,mina 2.0
*/
public class ServerMessageHandler implements IoHandler{ public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
System.out.println("server发生异常:"+ cause.toString());
} public void messageReceived(IoSession session, Object message) throws Exception {
MsgPack mp=(MsgPack)message;
System.out.println("收到client数据messageReceived----------:"+ mp.toString());
/*//请求协议
mp.setMsgMethod(3000);
mp.setMsgPack("我是server发的消息");
mp.setMsgLength(mp.getMsgPack().getBytes().length);
session.write(mp);*/
/*String content = mp.toString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String datetime = sdf.format(new Date());
System.out.println(datetime+"server接收到数据的内容为messageReceived----------: " + content);*/
// 拿到全部的clientSession
/*Collection<IoSession> sessions = session.getService().getManagedSessions().values();
// 向全部client发送数据
for (IoSession sess : sessions) {
sess.write(datetime + "\t" + content);
}*/ } public void messageSent(IoSession session, Object message) throws Exception {
/* System.out.println("server发送消息messageSent----------: "+ message);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String datetime = sdf.format(new Date());
System.out.println(datetime+"server发送消息messageSent----------: "+message.toString());*/
} public void sessionClosed(IoSession session) throws Exception {
System.out.println("关闭当前session: "+session.getId()+session.getRemoteAddress());
CloseFuture closeFuture = session.close(true);
closeFuture.addListener(new IoFutureListener<IoFuture>() {
public void operationComplete(IoFuture future) {
if (future instanceof CloseFuture) {
((CloseFuture) future).setClosed();
System.out.println("sessionClosed CloseFuture setClosed-->"+ future.getSession().getId());
}
}
});
} public void sessionCreated(IoSession session) throws Exception {
System.out.println("创建一个新连接:"+ session.getRemoteAddress()+" id: "+session.getId());
session.write("welcome to the chat room !");
} public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
System.out.println("当前连接处于空暇状态:"+ session.getRemoteAddress()+ status);
} public void sessionOpened(IoSession session) throws Exception {
System.out.println("打开一个session id:"+ session.getId()+" 空暇连接个数IdleCount: "+ session.getBothIdleCount());
}
}
自己定义协议类:
/**
* @see 自己定义协议
* @author Herman.Xiong
* @date 2014年6月11日 10:30:40
*/
public class MsgProtocol implements ProtocolCodecFactory{
private static final Charset charset=Charset.forName("UTF-8"); public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return new MsgProtocolDecoder(charset);
} public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return new MsgProtocolEncoder(charset);
}
}
协议解码类:
package com.minaqq.charset; 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.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput; import com.minaqq.domain.MsgPack;
/**
* @see 协议解码
* @author Herman.Xiong
* @date 2014年6月11日 16:47:24
*/
public class MsgProtocolDecoder extends CumulativeProtocolDecoder {
private Charset charset=null; public MsgProtocolDecoder() {
this(Charset.defaultCharset());
} public MsgProtocolDecoder(Charset charset) {
this.charset = charset;
} public void decode1(IoSession is, IoBuffer buf, ProtocolDecoderOutput out)
throws Exception {
buf.order(ByteOrder.LITTLE_ENDIAN);
MsgPack mp=new MsgPack();
//获取消息的内容长度
mp.setMsgLength(buf.getInt());
//获取消息的功能函数
mp.setMsgMethod(buf.getInt());
byte[] msg=new byte[mp.getMsgLength()];
buf.get(msg);
mp.setMsgPack(new String(msg,charset));
buf.flip();
out.write(mp);
} public void dispose(IoSession arg0) throws Exception { } public void finishDecode(IoSession arg0, ProtocolDecoderOutput arg1)
throws Exception { } public void decode0(IoSession arg0, IoBuffer arg1, ProtocolDecoderOutput arg2)
throws Exception {
int limit = arg1.limit();
byte[] bytes = new byte[limit];
arg1.get(bytes);
arg2.write(bytes);
} protected boolean doDecode(IoSession session, IoBuffer ioBuffer, ProtocolDecoderOutput out) throws Exception {
ioBuffer.order(ByteOrder.LITTLE_ENDIAN);
MsgPack mp = (MsgPack) session.getAttribute("nac-msg-pack"); // 从session对象中获取“xhs-upload”属性值
if(null==mp){
if (ioBuffer.remaining() >= 8) {
//取消息体长度
int msgLength = ioBuffer.getInt();
int msgMethod = ioBuffer.getInt();
mp=new MsgPack();
mp.setMsgLength(msgLength);
mp.setMsgMethod(msgMethod);
session.setAttribute("nac-msg-pack",mp);
return true;
}
return false;
}
if(ioBuffer.remaining()>=mp.getMsgLength()){
byte [] msgPack=new byte[mp.getMsgLength()];
ioBuffer.get(msgPack);
mp.setMsgPack(new String(msgPack,charset));
session.removeAttribute("nac-msg-pack");
out.write(mp);
return true;
}
return false;
} }
协议编码类:
package com.minaqq.charset; import java.io.NotSerializableException;
import java.io.Serializable;
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.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput; import com.minaqq.domain.MsgPack; public class MsgProtocolEncoder extends ProtocolEncoderAdapter{
private Charset charset=null; public MsgProtocolEncoder(Charset charset) {
this.charset = charset;
}
//在此处实现对MsgProtocolEncoder包的编码工作,并把它写入输出流中
public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
if(message instanceof MsgPack){
MsgPack mp = (MsgPack) message;
IoBuffer buf = IoBuffer.allocate(mp.getMsgLength());
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.setAutoExpand(true);
//设置消息内容的长度
buf.putInt(mp.getMsgLength());
//设置消息的功能函数
buf.putInt(mp.getMsgMethod());
if (null != mp.getMsgPack()) {
buf.put(mp.getMsgPack().getBytes(charset));
}
buf.flip();
out.write(buf);
out.flush();
buf.free();
}
}
public void dispose() throws Exception {
} public void encode0(IoSession arg0, Object arg1, ProtocolEncoderOutput arg2)
throws Exception {
if (!(arg1 instanceof Serializable)) {
throw new NotSerializableException();
}
IoBuffer buf = IoBuffer.allocate(64);
buf.setAutoExpand(true);
buf.putObject(arg1); int objectSize = buf.position() - 4;
if (objectSize > 1024) {
throw new IllegalArgumentException("The encoded object is too big: " + objectSize + " (> " + 1024
+ ')');
} buf.flip();
arg2.write(buf);
} }
协议实体类:
package com.minaqq.domain; import java.io.Serializable; /**
* @see 自己定义数据包
* @author Herman.Xiong
* @date 2014年6月11日 11:31:45
*/
public class MsgPack implements Serializable{
/**
* 序列化和反序列化的版本
*/
private static final long serialVersionUID = 1L;
//消息长度
private int msgLength;
//消息方法
private int msgMethod;
//消息包内容
private String msgPack; public MsgPack() {} public int getMsgLength() {
return msgLength;
} public void setMsgLength(int msgLength) {
this.msgLength = msgLength;
} public int getMsgMethod() {
return msgMethod;
} public void setMsgMethod(int msgMethod) {
this.msgMethod = msgMethod;
} public String getMsgPack() {
return msgPack;
} public void setMsgPack(String msgPack) {
this.msgPack = msgPack;
} public MsgPack(int msgLength, int msgMethod, String msgPack) {
this.msgLength = msgLength;
this.msgMethod = msgMethod;
this.msgPack = msgPack;
} public String toString() {
return "MsgPack [msgLength=" + msgLength + ", msgMethod=" + msgMethod
+ ", msgPack=" + msgPack + "]";
} }
心跳信息工厂类:
package com.minaqq.server; import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
/**
* @see 发送心跳包的内容
* getResponse()---->isResponse();获取数据推断心跳事件(目的是推断是否触发心跳超时异常)
* isRequest()----->getRequest(); 写回数据是心跳事件触发的数据(目的写回给server(client)心跳包)
* @author Herman.Xiong
*/
public class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory{ //心跳包内容
private static final String HEARTBEATREQUEST = "HEARTBEATREQUEST";
private static final String HEARTBEATRESPONSE = "HEARTBEATRESPONSE"; /**
* @see 返回给client的心跳包数据 return 返回结果才是client收到的心跳包数据
* @author Herman.Xiong
*/
public Object getRequest(IoSession session) {
return HEARTBEATREQUEST;
} /**
* @see 接受到的client数据包
* @author Herman.Xiong
*/
public Object getResponse(IoSession session, Object request) {
return request;
} /**
* @see 推断是否是client发送来的的心跳包此推断影响 KeepAliveRequestTimeoutHandler实现类推断是否心跳包发送超时
* @author Herman.Xiong
*/
public boolean isRequest(IoSession session, Object message) {
if(message.equals(HEARTBEATRESPONSE)){
System.out.println("接收到client心数据包引发心跳事件 心跳数据包是》》" + message);
return true;
}
return false;
} /**
* @see 推断发送信息是否是心跳数据包此推断影响 KeepAliveRequestTimeoutHandler实现类 推断是否心跳包发送超时
* @author Herman.Xiong
*/
public boolean isResponse(IoSession session, Object message) {
if(message.equals(HEARTBEATREQUEST)){
System.out.println("server发送数据包中引发心跳事件: " + message);
return true;
}
return false;
}
}
心跳业务处理类:
package com.minaqq.server; import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
/**
* @see 当心跳超时时的处理,也能够用默认处理 这里like
* KeepAliveRequestTimeoutHandler.LOG的处理
* @author Herman.Xiong
*/
public class KeepAliveRequestTimeoutHandlerImpl implements KeepAliveRequestTimeoutHandler {
/**
* @see org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler心跳超时处理
* @author Herman.Xiong
*/
public void keepAliveRequestTimedOut(KeepAliveFilter filter,
IoSession session) throws Exception {
System.out.println("server端心跳包发送超时处理(即长时间没有发送(接受)心跳包)---关闭当前长连接");
CloseFuture closeFuture = session.close(true);
closeFuture.addListener(new IoFutureListener<IoFuture>() {
public void operationComplete(IoFuture future) {
if (future instanceof CloseFuture) {
((CloseFuture) future).setClosed();
System.out.println("sessionClosed CloseFuture setClosed-->"+ future.getSession().getId());
}
}
});
}
}
server发送数据包的线程类:
package com.minaqq.worker; import java.util.Map; import org.apache.mina.core.session.IoSession; import com.minaqq.domain.MsgPack;
import com.minaqq.server.ServerMsgProtocol;
import com.minaqq.utils.XmlUtils;
/**
* @see server端发送数据
* @author Herman.Xiong
* @date 2014年6月9日 10:38:59
*/
public class ServerSendMsgThread extends Thread{ public void run() {
while(true){
if(null!=ServerMsgProtocol.getAcceptor()){
System.out.println("MinaServer.getAcceptor().getManagedSessionCount() is "+ServerMsgProtocol.getAcceptor().getManagedSessionCount()); Map<Long, IoSession> map=ServerMsgProtocol.getAcceptor().getManagedSessions();
for (Long key : map.keySet()) {
IoSession is = map.get(key);
//SocketAddress sa=is.getRemoteAddress();
//InetSocketAddress isa=(InetSocketAddress)sa;
//is.write("我是中文測试"+"session id is "+key+" hostName:"+isa.getHostName()+" address:"+isa.getAddress()+" port:"+isa.getPort()+" isa.toString:"+isa.toString());
MsgPack mp=new MsgPack();
//请求协议
mp.setMsgMethod(1000);
//mp.setMsgPack("我是服务端");
String str="";
for (int i = 0; i < 100; i++) {
str+=XmlUtils.getXml();
}
mp.setMsgPack(str);
mp.setMsgLength(mp.getMsgPack().getBytes().length);
try {
is.write(mp);
} catch (Exception e) {
e.printStackTrace();
}
}
}else {
System.out.println("MinaServer.getAcceptor is null ");
}
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
client測试类:
package com.minaqq.test; import com.minaqq.client.ClientMsgProtocol;
import com.minaqq.domain.MsgPack;
import com.minaqq.worker.ClientSendMsgThread; public class MsgClientTest {
public static void main(String[] args) {
ClientMsgProtocol.clientStart();
System.out.println("client启动成功......");
ClientSendMsgThread csmt=new ClientSendMsgThread();
csmt.start();
/*MsgPack mp=new MsgPack();
//请求协议
mp.setMsgMethod(2000);
mp.setMsgPack("我是client");
mp.setMsgLength(mp.getMsgPack().getBytes().length);
ClientMsgProtocol.getIoSession().write(mp);*/
System.out.println("client工作线程启动成功......");
}
}
client创建连接类:
package com.minaqq.client; import java.net.InetSocketAddress; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LogLevel;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.minaqq.protocol.MsgProtocol; /**
* @see 模拟client;
* 用于连接服务端。并向服务端发送消息
* @author Herman.Xiong
* @date 2013年11月26日 11:27:50
* @version 1.0
* @serial jdk 1.6
*/
public class ClientMsgProtocol { private static NioSocketConnector connector ; private static IoSession is; public static NioSocketConnector getConnector(){
if(null==connector){
// 创建非堵塞的server端的Socket连接
connector = new NioSocketConnector();
}
return connector;
} public static IoSession getIoSession(){
return is;
} public static void clientStart(){
// 创建client连接器
NioSocketConnector connector = getConnector();
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MsgProtocol()));
LoggingFilter loggingFilter = new LoggingFilter();
loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO);
loggingFilter.setMessageSentLogLevel(LogLevel.INFO);
connector.getFilterChain().addLast("logger", loggingFilter);
connector.getSessionConfig().setReceiveBufferSize(2048*5000);//接收缓冲区1M
connector.setConnectTimeoutMillis(30000); // 设置连接超时
connector.setHandler(new TimeClientHandler());// 设置消息处理器
ConnectFuture cf = connector.connect(new InetSocketAddress("10.10.2.136",8888));// 建立连接
cf.awaitUninterruptibly();// 等待连接创建完毕
try {
is=cf.getSession();
//getIoSession().write(new String(XmlUtils.getXml().getBytes("UTF-8")));// 发送消息
} catch (Exception e) {
e.printStackTrace();
}
} }
client消息处理事件类:
package com.minaqq.client; import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession; import com.minaqq.domain.MsgPack; /**
* @see 处理接收client消的息事件
* @author Herman.Xiong
* @date 2013年11月26日 11:23:32
* @version 1.0
* @since jdk1.6
*/
public class TimeClientHandler implements IoHandler{ /**
* 接收client发送的消息
*/
public void messageReceived(IoSession session, Object message) throws Exception {
MsgPack mp=(MsgPack)message;
System.out.println("收到服务端发来的消息:"+mp.toString());// 显示接收到的消息
} public void exceptionCaught(IoSession arg0, Throwable arg1)
throws Exception { } public void messageSent(IoSession arg0, Object arg1) throws Exception { } public void sessionClosed(IoSession arg0) throws Exception { } public void sessionCreated(IoSession arg0) throws Exception { } public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception { } public void sessionOpened(IoSession arg0) throws Exception { }
}
client发送消息线程类:
package com.minaqq.worker; import com.minaqq.client.ClientMsgProtocol;
import com.minaqq.domain.MsgPack;
/**
* @see 模拟client发送数据
* @author Herman.Xiong
* @date 2014年6月9日 10:38:59
*/
public class ClientSendMsgThread extends Thread{
public void run() {
while(true){
if(null!=ClientMsgProtocol.getConnector()){
try {
//ClientMsgProtocol.getIoSession().write(new String("我是client".getBytes("UTF-8")));
MsgPack mp=new MsgPack();
//请求协议
mp.setMsgMethod(2000);
mp.setMsgPack("我是client");
mp.setMsgLength(mp.getMsgPack().getBytes().length);
ClientMsgProtocol.getIoSession().write(mp);
} catch (Exception e) {
e.printStackTrace();
}
}else {
System.out.println("MinaServer.getAcceptor is null ");
}
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
发送xml消息的工具类:
package com.minaqq.utils; import com.minaqq.domain.Address;
import com.minaqq.domain.House;
import com.minaqq.domain.Person;
import com.minaqq.domain.PhoneNumber;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver; public class XmlUtils { public static void testXStream(){
XStream xstream=new XStream(new DomDriver());
xstream.alias("PERSON", Person.class);
xstream.alias("ADDRESS",Address.class);
xstream.alias("PHONENUMBER", PhoneNumber.class);
xstream.alias("HOUSE", House.class);
Person person=(Person)xstream.fromXML(XmlUtils.getXml());
System.out.println(person.toString());
} public static String getXml(){
StringBuffer sb=new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");//
sb.append("<PERSON firstName=\"Herman\">");
sb.append("<lastName>Xiong</lastName> ");
sb.append("<phonex>");
sb.append("<code>0</code>");
sb.append("<number>1234567</number>");
sb.append("</phonex>");
sb.append("<fax>");
sb.append("<code>0</code>");
sb.append("<number>7654321</number>");
sb.append("</fax>");
sb.append("<addList>");
sb.append("<ADDRESS>");
sb.append("<add>上海市</add>");
sb.append("<zipCode>123456</zipCode>");
sb.append("</ADDRESS>");
sb.append("</addList>");
sb.append("<house>");
sb.append("<HOUSE>");
sb.append("<size>300万</size>");
sb.append("<price>120平方米</price>");
sb.append("</HOUSE>");
sb.append("<HOUSE>");
sb.append("<size>500万</size>");
sb.append("<price>130平方米</price>");
sb.append("</HOUSE>");
sb.append("<HOUSE>");
sb.append("<size>160万</size>");
sb.append("<price>61.5平方米</price>");
sb.append("</HOUSE>");
sb.append("</house>");
sb.append("</PERSON>\n");
return sb.toString();
}
}
xml有关的实体类:
package com.minaqq.domain; import java.util.Arrays;
import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; public class Person {
@XStreamAsAttribute
private String firstName;
private String lastName;
private PhoneNumber phonex;
private PhoneNumber fax;
private List<Address> addList;
private House[] house;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public PhoneNumber getPhonex() {
return phonex;
}
public void setPhonex(PhoneNumber phonex) {
this.phonex = phonex;
}
public PhoneNumber getFax() {
return fax;
}
public void setFax(PhoneNumber fax) {
this.fax = fax;
}
public List<Address> getAddList() {
return addList;
}
public void setAddList(List<Address> addList) {
this.addList = addList;
}
public House[] getHouse() {
return house;
}
public void setHouse(House[] house) {
this.house = house;
}
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName=firstName;
this.lastName=lastName;
}
public Person(String firstName, String lastName, PhoneNumber phonex,
PhoneNumber fax) {
this.firstName = firstName;
this.lastName = lastName;
this.phonex = phonex;
this.fax = fax;
}
public Person(String firstName, String lastName, PhoneNumber phonex,
PhoneNumber fax, List<Address> addList) {
this.firstName = firstName;
this.lastName = lastName;
this.phonex = phonex;
this.fax = fax;
this.addList = addList;
}
public Person(String firstName, String lastName, PhoneNumber phonex,
PhoneNumber fax, List<Address> addList, House[] house) {
this.firstName = firstName;
this.lastName = lastName;
this.phonex = phonex;
this.fax = fax;
this.addList = addList;
this.house = house;
}
@Override
public String toString() {
return "Person [addList=" + addList + ", fax=" + fax + ", firstName="
+ firstName + ", house=" + Arrays.toString(house)
+ ", lastName=" + lastName + ", phonex=" + phonex + "]";
}
}
xml有关的实体类:
package com.minaqq.domain; public class Address {
private String add;
private String zipCode;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public Address() {
}
public Address(String add, String zipCode) {
this.add = add;
this.zipCode = zipCode;
}
@Override
public String toString() {
return "Address [add=" + add + ", zipCode=" + zipCode + "]";
}
}
xml有关的实体类:
package com.minaqq.domain; public class PhoneNumber {
private int code;
private int number;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public PhoneNumber(){}
public PhoneNumber(int code,int number){
this.code=code;
this.number=number;
}
@Override
public String toString() {
return "PhoneNumber [code=" + code + ", number=" + number + "]";
}
}
xml有关的实体类:
package com.minaqq.domain; public class House {
private String size;
private String price;
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public House() {
}
public House(String size, String price) {
this.size = size;
this.price = price;
}
@Override
public String toString() {
return "House [price=" + price + ", size=" + size + "]";
}
}
执行效果图,服务图片:
client图片:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveG10YmxvZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
OK,到此结束了,欢迎大家关注我的个人博客。
学习资料已经源代码下载请点击:http://download.csdn.net/download/xmt1139057136/7487611
如有不懂。请大家增加qq群:135430763共同学习。
mina的编码和解码以及断包的处理,发送自己定义协议,仿qq聊天,发送xml或json的更多相关文章
- mina框架tcpt通讯接收数据断包粘包处理
用mina做基于tcp,udp有通讯有段时间了,一直对编码解码不是很熟悉,这次做项目的时候碰到了断包情况,贴一下解决过程, 我接受数据格式如下图所示: unit32为c++中数据类型,代表4个字节,由 ...
- NIO框架之MINA源码解析(四):粘包与断包处理及编码与解码
1.粘包与段包 粘包:指TCP协议中,发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.造成的可能原因: 发送端需要等缓冲区满才发送出去,造成粘包 接收 ...
- 【MINA】粘包断包处理
1.先解释下什么叫粘包和断包 粘包 就是数据以字节的形式在网络中传输,一个数据包的字节可能经过多次的读取粘合才能形成一个完整的数据包 断包 一次读取的内容可能包含了两个或多个数据包的内容,那么我们必须 ...
- Mina框架断包、粘包问题解决方式
Mina框架断包.粘包问题解决方式 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然.也能够提供JAVA 对象的序 ...
- mina websocket 粘包、断包、(丢包)解决心得
被这3个(其实是2个)问题坑惨了,目前没发现存在丢包问题,之前认为的丢包问题事实是不存在的. 粘包和断包的情况是存在的,这两个问题不怕,只要发送接收到的数据包顺序没有被打乱颠倒,一切都好办. 容易掉的 ...
- android Java BASE64编码和解码一:基础
今天在做Android项目的时候遇到一个问题,需求是向服务器上传一张图片,要求把图片转化成图片流放在 json字符串里传输. 类似这样的: {"name":"jike&q ...
- speex的基本编码和解码流程
最近在研究speex的编码和解码流程 之前在IM上用到的都是发语音片段,这个很简单,只需要找到googlecode上gauss的代码,然后套一下就可以用了. 不过googlecode要关闭,有人将他导 ...
- Dubbo中编码和解码的解析
(这里做的解析不是很详细,等到走完整个流程再来解析)Dubbo中编解码的工作由Codec2接口的实现来处理,回想一下第一次接触到Codec2相关的内容是在服务端暴露服务的时候,根据具体的协议去暴露服务 ...
- NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用
NET MVC全局异常处理(一) 目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...
随机推荐
- duilib之源码分析
<duilib之源码分析>1 stdAfx.h * lengthof(x) 计算数组长度宏 * MAX 两值最大 * MIN 两值最小 * CLAMP(x,a,b) x在a,b之间则取 ...
- [ASP.NET]利用itextsharp将GridView汇出PDF档
原文 [ASP.NET]利用itextsharp将GridView汇出PDF档 最近在讨论区看到有人说itextsharp可以把网页变成PDF 小弟就去抓一下itextsharp来玩玩,先教大家最实用 ...
- 配置Jenkins的slave节点的详细步骤适合windows等其他平台(转)
@ 新建一个slave节点在Jenkins服务器上 1,进入Jenkins的主界面,进入“Manage Jenkins” 页面: 2,点击如下图中的“Manage Nodes”: 3,进入页面后点 ...
- kiddouk/redisco
kiddouk/redisco A Python Library for Simple Models and Containers Persisted in Redis
- Swift - 获取字符串的MD5值
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现. ...
- WCF技术剖析之十六:数据契约的等效性和版本控制
原文:WCF技术剖析之十六:数据契约的等效性和版本控制 数据契约是对用于交换的数据结构的描述,是数据序列化和反序列化的依据.在一个WCF应用中,客户端和服务端必须通过等效的数据契约方能进行有效的数据交 ...
- 生成md5密码
mysql> select md5(concat((select md5("admin123") from test limit 1),'`xx')) from test; ...
- 重载new delete操作符是怎么调用的
自定义的new操作符是怎么对英语new 一个对象的?自定义的delete操作符什么情况下得到调用?new一个对象时出现异常需要我操心内存泄露吗?下面的一个例子帮我们解开所有的疑惑. 1. 调用规则 ...
- 正则表达式概述与JAVA中正则表达式的应用
编程或者电脑使用过程中,经常需要对字符串进行 匹配,查找,替换,判断.如果单纯用代码 if () ,whlie 什么的进行比较复杂麻烦.正则表达式是一种强大灵活的文本处理工具,专门对字符串进行匹配,查 ...
- 终于懂了:WM_PAINT 与 WM_ERASEBKGND(三种情况:用户操作,UpdateWindow,InvalidateRect产生的效果并不相同),并且用Delphi代码验证 good
一直对这两个消息的关系不是太了解,借重新深刻学习windows编程的机会研究一番. 1)当窗口从无效变为有效时,比方将部分覆盖的窗口恢复时会重绘窗口时:程序首先会通过发送其他消息调用DefWindow ...