Chinaunix首页 | 论坛 | 博客
  • 博客访问: 83187
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 340
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-02 20:25
文章分类

全部博文(31)

文章存档

2015年(2)

2014年(29)

我的朋友

分类: Java

2014-09-12 11:24:12

  TCP采用停止等待协议来避免数据在传输过程中丢失,一般的停止等待协议要求发送方在收到之前发送的数据后再发送剩余数据,为了提高数据发送的效率,TCP采用了一种累积确认的方式,这个协议为滑动窗口协议。由于网络双方的网速不尽相同,比如快的发送跟慢的接受,将导致接受服务器的接受缓冲区一直被填满,使得接受服务器拒绝接受数据,造成发送方不停重发送数据甚至连接被断开。所以滑动窗口协议的窗口大小是随着网络情况而动态变化的,无法保证一个应用上完整包被一次发送,难免出现断包现象。而延时确认以及重发机制,又难免会出现粘包的现象。
 

 解决断包与粘包问题必须为制定一个包规范,比如包的起始标志,包长度等。有了包规范后,解决起来就很简单了。在读取一个包数据后,根据规范分析这个包,如果数据不完整,只需将不完整的数据放入连接上下文即可。因为TCP是面向连接的,所以很容易为每个连接创建了Session。

例子:1F1F + len(1byte) + string + EFEF。len=length(string) utf-8。

点击(此处)折叠或打开

  1. public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
  2.             throws Exception {

  3.         // 取得上次未处理的数据包
  4.         IoBuffer lastBuf = (IoBuffer) session.getAttribute("buffer");
  5.         if (lastBuf == null)
  6.             lastBuf = IoBuffer.allocate(100).setAutoExpand(true);
  7.         // 跟本次数据合并
  8.         lastBuf.put(in);
  9.         lastBuf.flip(); // 转为读模式

  10.         final int head = 4 + 1; //head + len
  11.         String shead = "";
  12.         
  13.         while(lastBuf.hasRemaining()){
  14.             if(lastBuf.remaining() < head){ //断包
  15.                 lastBuf.compact();
  16.                 session.setAttribute("buffer", lastBuf);
  17.                 break;
  18.             }
  19.             shead = "" + (char)lastBuf.get()+ (char)lastBuf.get()+ (char)lastBuf.get()
  20.                     + (char)lastBuf.get();
  21.             if(!"1F1F".equals(shead))
  22.                 break;
  23.             int l = Integer.parseInt((char)lastBuf.get()+"", 10);
  24.             if(lastBuf.remaining() < l + 4){ //断包
  25.                 int pos = lastBuf.limit();
  26.                 lastBuf.clear();
  27.                 lastBuf.position(pos);
  28.                 session.setAttribute("buffer", lastBuf);
  29.                 break;
  30.             }
  31.              byte bytes[] = new byte[l];
  32.              lastBuf.get(bytes);
  33.             
  34.              String recvString = new String(bytes, "UTF-8");
  35.             
  36.              out.write(recvString);
  37.             
  38.              //EFEF
  39.              lastBuf.get();
  40.              lastBuf.get();
  41.              lastBuf.get();
  42.              lastBuf.get();
  43.              //去掉已读的完整包,如还有数据,则为粘包,继续处理
  44.              lastBuf.compact();
  45.              lastBuf.flip();
  46.         }
  47.     }

阅读(1531) | 评论(0) | 转发(0) |
0

上一篇:6.MINA-编解码

下一篇:8. MINA--开启监听

给主人留下些什么吧!~~