mina的编码和解码以及断包的处理,发送自定义协议,仿qq聊天,发送xml或json

简介: 最近一段时间以来,mina很火,和移动开发一样,异常的火爆。前面写了几篇移动开发的文章,都还不错,你们的鼓励就是我最大的动力。好了,废话少说。我们来看下tcp通讯吧。<br> tcp通讯对于java来说是很简单的。就是socket,也就是大家常说的套接字。大家不要把它看的很难。说白了tcp通讯其实就是数据流的读写。一条输入流,一条输出流。分别复杂发消息和接收消息。<br> 明白了这些,
最近一段时间以来,mina很火,和移动开发一样,异常的火爆。前面写了几篇移动开发的文章,都还不错,你们的鼓励就是我最大的动力。好了,废话少说。我们来看下tcp通讯吧。
tcp通讯对于java来说是很简单的。就是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 服务器启动类,字符串消息测试类
 * @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;
    }

}
服务器的消息处理:
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 处理服务器端消息
 * @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("服务器发生异常:"+ cause.toString());
    }

    public void messageReceived(IoSession session, Object message) throws Exception {
    	MsgPack mp=(MsgPack)message;
        System.out.println("收到客户端数据messageReceived----------:"+ mp.toString());
		/*//请求协议
		mp.setMsgMethod(3000);
		mp.setMsgPack("我是服务器发的消息");
		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+"服务器接收到数据的内容为messageReceived----------: " + content);*/
        // 拿到所有的客户端Session
        /*Collection<IoSession> sessions = session.getService().getManagedSessions().values();
        // 向所有客户端发送数据
        for (IoSession sess : sessions) {
            sess.write(datetime + "\t" + content);
        }*/
        
    }

    public void messageSent(IoSession session, Object message) throws Exception {
       /* System.out.println("服务器发送消息messageSent----------: "+ message);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String datetime = sdf.format(new Date());
        System.out.println(datetime+"服务器发送消息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(); 写回数据是心跳事件触发的数据(目的写回给服务器(客户端)心跳包)
 * @author Herman.Xiong
 */
public class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory{
	
	//心跳包内容
    private static final String HEARTBEATREQUEST = "HEARTBEATREQUEST";
    private static final String HEARTBEATRESPONSE = "HEARTBEATRESPONSE";
    
	/**
     * @see 返回给客户端的心跳包数据 return 返回结果才是客户端收到的心跳包数据
     * @author Herman.Xiong
     */
    public Object getRequest(IoSession session) {
        return HEARTBEATREQUEST;
    }

    /**
     * @see 接受到的客户端数据包
     * @author Herman.Xiong
     */
    public Object getResponse(IoSession session, Object request) {
        return request;
    }

    /**
     * @see 判断是否是客户端发送来的的心跳包此判断影响 KeepAliveRequestTimeoutHandler实现类判断是否心跳包发送超时
     * @author Herman.Xiong
     */
    public boolean isRequest(IoSession session, Object message) {
        if(message.equals(HEARTBEATRESPONSE)){
            System.out.println("接收到客户端心数据包引发心跳事件                 心跳数据包是》》" + message);
	        return true;
	    }
        return false;
    }

    /**
     * @see  判断发送信息是否是心跳数据包此判断影响 KeepAliveRequestTimeoutHandler实现类 判断是否心跳包发送超时
     * @author Herman.Xiong
     */
    public boolean isResponse(IoSession session, Object message) {
        if(message.equals(HEARTBEATREQUEST)){
            System.out.println("服务器发送数据包中引发心跳事件: " + 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("服务器端心跳包发送超时处理(即长时间没有发送(接受)心跳包)---关闭当前长连接");
        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());
                }
            }
        });
    }
}
服务器发送数据包的线程类:
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 服务器端发送数据
 * @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();
			}
		}
	}
}
客户端测试类:
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("客户端启动成功......");
		ClientSendMsgThread csmt=new ClientSendMsgThread();
		csmt.start();
		/*MsgPack mp=new MsgPack();
		//请求协议
		mp.setMsgMethod(2000);
		mp.setMsgPack("我是客户端");
		mp.setMsgLength(mp.getMsgPack().getBytes().length);
		ClientMsgProtocol.getIoSession().write(mp);*/
		System.out.println("客户端工作线程启动成功......");
	}
}
客户端创建连接类:
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 模拟客户端;
 * 用于连接服务端,并向服务端发送消息
 * @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(){
		// 创建客户端连接器
		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();
		}
	}
	
}
客户端消息处理事件类:
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 处理接收客户端消的息事件
 * @author Herman.Xiong
 * @date 2013年11月26日 11:23:32
 * @version 1.0
 * @since jdk1.6
 */
public class TimeClientHandler implements IoHandler{
	
	/**
	 * 接收客户端发送的消息
	 */
	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 {
		
	}
}
客户端发送消息线程类:
package com.minaqq.worker;

import com.minaqq.client.ClientMsgProtocol;
import com.minaqq.domain.MsgPack;
/**
 * @see 模拟客户端发送数据
 * @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("我是客户端".getBytes("UTF-8")));
					MsgPack mp=new MsgPack();
					//请求协议
					mp.setMsgMethod(2000);
					mp.setMsgPack("我是客户端");
					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 + "]";
	}
}

运行效果图,服务图片:


客户端图片:

OK,到此结束了,欢迎大家关注我的个人博客。

学习资料已经源码下载请点击:http://download.csdn.net/download/xmt1139057136/7487611

如有不懂,请大家加入qq群:135430763共同学习!

目录
相关文章
|
2月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
47 1
|
3月前
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
61 1
|
3月前
|
JSON API 网络架构
【Azure 媒体服务】使用编码预设文件(Preset.json)来自定义编码任务 -- 创建视频缩略图
【Azure 媒体服务】使用编码预设文件(Preset.json)来自定义编码任务 -- 创建视频缩略图
|
2月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
180 61
C# 中的 XML 与 JSON 数据处理
|
4月前
|
JSON 网络协议 JavaScript
站长在线工具箱网站JSON网页工具加解密编码制作网站源码
站长在线工具箱网站JSON网页工具加解密编码制作网站源码
72 2
|
22天前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。
|
1月前
|
XML JSON 数据可视化
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
本文详细介绍了不同数据集格式之间的转换方法,包括YOLO、VOC、COCO、JSON、TXT和PNG等格式,以及如何可视化验证数据集。
103 1
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
|
25天前
|
XML 数据格式 Windows
|
1月前
|
XML JSON 前端开发
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
388 0
|
3月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
93 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧