一、定义协议实体
1. import java.nio.charset.Charset;
2.
3. /**
4. * 自定义协议的消息体
5. */
6. public class MyMsg {
7. /**
8. * 消息长度
9. */
10. private Integer lenth;
11.
12. /**
13. * 发送人
14. */
15. private Long sender;
16.
17. /**
18. * 接收人
19. */
20. private Long receiver;
21.
22. /**
23. * 消息内容
24. */
25. private String content;
26.
27. public MyMsg() {
28.
29. }
30.
31. public Long getSender() {
32. return sender;
33. }
34.
35. public void setSender(Long sender) {
36. this.sender = sender;
37. }
38.
39. public Long getReceiver() {
40. return receiver;
41. }
42.
43. public void setReceiver(Long receiver) {
44. this.receiver = receiver;
45. }
46.
47. public String getContent() {
48. return content;
49. }
50.
51. public void setContent(String content) {
52. this.content = content;
53. }
54.
55. /**
56. * 先计算长度,再返回。这里长度包含长度本身的字节
57. */
58. public Integer getLenth() {
59.
60. this.lenth = 4 + 8*2 + this.content.getBytes(Charset.forName("utf-8")).length;
61.
62. return lenth;
63. }
64.
65. public MyMsg(Long sender, Long receiver, String content) {
66. this.sender = sender;
67. this.receiver = receiver;
68. this.content = content;
69. }
70.
71. @Override
72. public String toString() {
73. return "MyMsg [lenth=" + this.getLenth() + ", sender=" + sender + ", receiver="
74. ", content=" + content + "]";
75. }
76.
77. }
二、定义编解码器
1、编码器
1. import java.nio.charset.Charset;
2. import java.nio.charset.CharsetEncoder;
3. import org.apache.mina.core.buffer.IoBuffer;
4. import org.apache.mina.core.session.IoSession;
5. import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
6. import org.apache.mina.filter.codec.ProtocolEncoderOutput;
7.
8. /**
9. * 编码器
10. */
11. public class MyEncoder extends ProtocolEncoderAdapter {
12.
13. @Override
14. public void encode(IoSession session, Object message, ProtocolEncoderOutput encoderOutput)
15. throws Exception {
16.
17. "utf-8").newEncoder();
18.
19. MyMsg msg = (MyMsg) message;
20.
21. // Mina IoBuffer
22. 100).setAutoExpand(true);
23.
24. buffer.putInt(msg.getLenth());
25. buffer.putLong(msg.getSender());
26. buffer.putLong(msg.getReceiver());
27.
28. // 有多个可变长度的属性时,可约定通过定义可变属性的最大长度(多余截取不足补齐)或put之前put其长度等方式处理
29. buffer.putString(msg.getContent(), ce);
30.
31. buffer.flip();
32.
33. encoderOutput.write(buffer);
34.
35. }
36.
37. }
2、解码器
1. import java.nio.charset.Charset;
2. import java.nio.charset.CharsetDecoder;
3. import org.apache.mina.core.buffer.IoBuffer;
4. import org.apache.mina.core.session.IoSession;
5. import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
6. import org.apache.mina.filter.codec.ProtocolDecoderOutput;
7.
8. /**
9. * 解码器可继承ProtocolEncoderAdapter,但它不利于处理粘包的情况
10. */
11. public class MyDecoder extends CumulativeProtocolDecoder {
12.
13. @Override
14. protected boolean doDecode(IoSession session, IoBuffer buffer, ProtocolDecoderOutput decoderOutput)
15. throws Exception {
16. "utf-8").newDecoder();
17.
18. /**
19. * 这里,如果长度不够20字节,就认为这条消息还没有累积完成
20. */
21. if(buffer.remaining() < 20){
22. /**
23. * 停止调用decode,但如果还有数据没有读取完,将含有剩余数据的IoBuffer保存到IoSession中,
24. * 当有新数据包来的时候再和新的合并后再调用decoder解码
25. * 注意:没有消费任何数据时不能返回true,否则会抛出异常
26. */
27. return false;
28.
29. else{
30.
31. int length = buffer.getInt();
32.
33. new MyMsg();
34.
35. msg.setSender(buffer.getLong());
36. msg.setReceiver(buffer.getLong());
37.
38. // 注意:20 = 消息长度的字节 + 发送人和接收人的字节
39. 20, de));
40.
41. decoderOutput.write(msg);
42.
43. /**
44. * CumulativeProtocolDecoder会再次调用decoder,并把剩余的数据发下来继续解码
45. */
46. return true;
47. }
48. }
49.
50. }
3、编解码工厂
[java] view plain copy
1. import org.apache.mina.core.session.IoSession;
2. import org.apache.mina.filter.codec.ProtocolCodecFactory;
3. import org.apache.mina.filter.codec.ProtocolDecoder;
4. import org.apache.mina.filter.codec.ProtocolEncoder;
5.
6. /**
7. * 编解码工厂
8. */
9. public class MyCoderFactory implements ProtocolCodecFactory{
10.
11. private MyDecoder decoder;
12. private MyEncoder encoder;
13.
14. public MyCoderFactory() {
15. this.decoder = new MyDecoder();
16. this.encoder = new MyEncoder();
17. }
18.
19. @Override
20. public ProtocolDecoder getDecoder(IoSession session) throws Exception {
21. return decoder;
22. }
23.
24. @Override
25. public ProtocolEncoder getEncoder(IoSession session) throws Exception {
26. return encoder;
27. }
28.
29. }
三、服务器端
1、运行类
[java] view plain copy
1. import java.io.IOException;
2. import .InetSocketAddress;
3. import .SocketAddress;
4. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
5. import org.apache.mina.core.service.IoAcceptor;
6. import org.apache.mina.core.session.IdleStatus;
7. import org.apache.mina.filter.codec.ProtocolCodecFilter;
8. import org.apache.mina.filter.logging.LoggingFilter;
9. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
10.
11. public class ServerMain {
12.
13. public static void main(String[] args) throws IOException {
14.
15. // 在服务器端创建一个监听连接的接收器 基于tcp/ip
16. new NioSocketAcceptor();
17.
18. // 绑定的端口
19. new InetSocketAddress("localhost", 8888);
20.
21. // 获取过滤器链
22. DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
23.
24. // 添加日志过滤器
25. "logger", new LoggingFilter());
26.
27. // 配置自定义的编解码器
28. "mycodec", new ProtocolCodecFilter(new MyCoderFactory()));
29.
30. // 添加数据处理的处理器
31. new ServerHandler());
32.
33. // 进行配置信息的设置
34. 100);
35. 10);
36.
37. // 绑定服务器端口
38. acceptor.bind(address);
39.
40. "服务器开始在 8888 端口监听.......");
41.
42. }
43. }
2、Handler
[java] view plain copy
1. import org.apache.mina.core.service.IoHandlerAdapter;
2. import org.apache.mina.core.session.IdleStatus;
3. import org.apache.mina.core.session.IoSession;
4.
5. public class ServerHandler extends IoHandlerAdapter{
6.
7. /**
8. * 接受消息
9. */
10. public void messageReceived(IoSession session, Object message)
11. throws Exception {
12. MyMsg msg = (MyMsg) message;
13. "服务器端接收到的消息:" + msg);
14.
15. // 返回一个消息给客户端
16. new MyMsg(10000L, 10001L, "你好,这是来自服务器的应答!");
17. session.write(msg);
18. }
19.
20. /**
21. * 发送消息
22. */
23. public void messageSent(IoSession session, Object message) throws Exception {
24. "服务器端开始发送消息...");
25. super.messageSent(session, message);
26. }
27.
28. /**
29. * 会话开启
30. */
31. public void sessionOpened(IoSession session) throws Exception {
32. "服务端会话已打开...");
33. super.sessionOpened(session);
34. }
35.
36. /**
37. * 异常处理
38. */
39. public void exceptionCaught(IoSession session, Throwable cause)
40. throws Exception {
41. "服务端发生异常了...");
42. cause.printStackTrace();
43. }
44.
45. /**
46. * 会话关闭
47. */
48. public void sessionClosed(IoSession session) throws Exception {
49. "服务端会话已关闭...");
50. super.sessionClosed(session);
51. }
52.
53. /**
54. * 会话创建
55. */
56. public void sessionCreated(IoSession session) throws Exception {
57. "服务端会话已创建...");
58. super.sessionCreated(session);
59. }
60.
61. /**
62. * 连接空闲
63. */
64. public void sessionIdle(IoSession session, IdleStatus status)
65. throws Exception {
66. "服务端连接空闲中...");
67. super.sessionIdle(session, status);
68. }
69. }
四、客户端
1、连接类
[java] view plain copy
1. import .InetSocketAddress;
2. import .SocketAddress;
3. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
4. import org.apache.mina.core.future.ConnectFuture;
5. import org.apache.mina.filter.codec.ProtocolCodecFilter;
6. import org.apache.mina.filter.logging.LoggingFilter;
7. import org.apache.mina.transport.socket.nio.NioSocketConnector;
8.
9. public class ClientMain {
10. public static void main(String[] args) {
11.
12. // 创建客户端连接器 基于tcp/ip
13. new NioSocketConnector();
14.
15. // 连接的地址和端口
16. new InetSocketAddress("localhost",8888);
17.
18. // 获取过滤器链
19. DefaultIoFilterChainBuilder chain = connector.getFilterChain();
20.
21. // 配置日志过滤器和自定义编解码器
22. "logger", new LoggingFilter());
23. "mycodec",new ProtocolCodecFilter(new MyCoderFactory()));
24.
25. // 添加处理器
26. new ClientHandler());
27.
28. // 连接到服务器
29. ConnectFuture future = connector.connect(address);
30.
31. // 等待连接创建完成
32. future.awaitUninterruptibly();
33.
34. // 会话创建后发送消息到服务器
35. new MyMsg(10001L, 10000L, "你好,这是来自客户端的请求!");
36. future.getSession().write(msg);
37.
38. // 等待28000毫秒后连接断开
39. 28000);
40.
41. // 关闭连接
42. connector.dispose();
43.
44. }
45. }
2、Handler
[java] view plain copy
1. import org.apache.mina.core.service.IoHandlerAdapter;
2. import org.apache.mina.core.session.IoSession;
3.
4. public class ClientHandler extends IoHandlerAdapter{
5.
6. /**
7. * 接收消息
8. */
9. public void messageReceived(IoSession session, Object message)
10. throws Exception {
11. "客户端接收到的消息:" + (MyMsg)message);
12. }
13.
14. /**
15. * 发送消息
16. */
17. public void messageSent(IoSession session, Object message) throws Exception {
18. "客户端发送消息...");
19. super.messageSent(session, message);
20.
21. }
22.
23. /**
24. * 会话创建
25. */
26. public void sessionOpened(IoSession session) throws Exception {
27.
28. "客户端已经连接到了服务器...");
29.
30. }
31.
32. /**
33. * 会话关闭
34. */
35. public void sessionClosed(IoSession session) throws Exception {
36. "连接关闭...");
37. super.sessionClosed(session);
38. }
39.
40. }
五、结果
1、服务器端
2、客户端