在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息。理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次read。但是,现实不总是按照剧本来走。

MINA官方文档节选:

TCP guarantess delivery of all packets in the correct order. But there is no guarantee that one write operation on the sender-side will result in one read event on the receiving side. One call of IoSession.write(Object message) by the sender can result in multiple messageReceived(IoSession session, Object message) events on the receiver; and multiple calls of IoSession.write(Object message) can lead to a single messageReceived event.

Netty官方文档节选:

In a stream-based transport such as TCP/IP, received data is stored into a socket receive buffer. Unfortunately, the buffer of a stream-based transport is not a queue of packets but a queue of bytes. It means, even if you sent two messages as two independent packets, an operating system will not treat them as two messages but as just a bunch of bytes. Therefore, there is no guarantee that what you read is exactly what your remote peer wrote.

上面两段话表达的意思相同:TCP是基于字节流的协议,它只能保证一方发送和另一方接收到的数据的字节顺序一致,但是,并不能保证一方每发送一条消息,另一方就能完整的接收到一条信息。有可能发送了两条对方将其合并成一条,也有可能发送了一条对方将其拆分成两条。

对此,MINA的官方文档提供了以下几种解决方案:

1、use fixed length messages

使用固定长度的消息。比如每个长度4字节,那么接收的时候按每条4字节拆分就可以了。

2、use a fixed length header that indicates the length of the body

使用固定长度的Header,Header中指定Body的长度(字节数),将信息的内容放在Body中。例如Header中指定的Body长度是100字节,那么Header之后的100字节就是Body,也就是信息的内容,100字节的Body后面就是下一条信息的Header了。

3、using a delimiter; for example many text-based protocols append a newline (or CR LF pair) after every message

使用分隔符。例如许多文本内容的协议会在每条消息后面加上换行符(CR LF,即"\r\n"),也就是一行一条消息。当然也可以用其他特殊符号作为分隔符,例如逗号、分号等等。

mina server

   IoAcceptor acceptor = new NioSocketAcceptor();  // 添加一个Filter,用于接收、发送的内容按照"\r\n"分割  acceptor.getFilterChain().addLast("codec",   new ProtocolCodecFilter((ProtocolCodecFactory) new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n")));  acceptor.setHandler((IoHandler) new TcpServerHandle2());  acceptor.bind(new InetSocketAddress(8080));

netty server

    ServerBootstrap b = new ServerBootstrap();  b.group(bossGroup, workerGroup)  .channel(NioServerSocketChannel.class)  .childHandler(new ChannelInitializer<SocketChannel>() {  @Override  public void initChannel(SocketChannel ch)  throws Exception {  ChannelPipeline pipeline = ch.pipeline();  // LineBasedFrameDecoder按行分割消息  pipeline.addLast(new LineBasedFrameDecoder(80));  // 再按UTF-8编码转成字符串  pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));  pipeline.addLast(new TcpServerHandler2());  }  });  ChannelFuture f = b.bind(8080).sync();  f.channel().closeFuture().sync();

client

socket = new Socket("localhost", 8080);  out = socket.getOutputStream();  // 请求服务器  String lines = "床前明月光\r\n疑是地上霜\r\n举头望明月\r\n低头思故乡\r\n";  byte[] outputBytes = lines.getBytes("UTF-8");  out.write(outputBytes);  out.flush();

  

但是这样是有问题的,如果消息内容本身就有换行符,这个肯定是不对的

  原文地址:http://www.cnblogs.com/wucao/p/3936559.html

转载于:https://www.cnblogs.com/xiaoblog/p/5640661.html

mina、netty消息边界问题(采用换行符)相关推荐

  1. mina、netty消息边界问题

    mina.netty消息边界问题(采用换行符) 在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立 ...

  2. 回车符,换行符的区别

    首先介绍一下"回车"(carriage return,'\r')和"换行"(line feed,'\n')这两个概念的来历和区别.在计算机还没有出现之前,有一种 ...

  3. linux的回车和换行符,【Base】linux和windows下的“回车符”和“换行符”

    Date: 2018.7.2 _____________________________________________________________________________________ ...

  4. Windows、Linux和MAC的CR, LF, CR/LF换行符

    在文本处理中, CR, LF, CR/LF是不同操作系统上使用的换行符. Dos和windows: 采用回车+换行CR/LF表示下一行.  UNIX/Linux  : 采用换行符LF表示下一行.  M ...

  5. 关于C之文件结尾EOF与二进制文件换行符

    文件结尾: 计算机操作系统要以某种方式判断文件的开始和结束. 检测文件结尾的一种方法是, 在文件末尾放一个特殊的字符标记文件尾. CP/M. IBMDOS和MS-DOS的文本文件曾经用过这种方法. 如 ...

  6. 计算机中的换行符、回车符、\n、\r、\n\r 怎么区分

    \n是换行,英文是New line \r是回车,英文是Carriage return '\r'是回车,前者使光标到行首,(carriage return) '\n'是换行,后者使光标下移一行,(lin ...

  7. NASM汇编教程翻译07 第七讲 换行符

    英文原版地址:NASM Assembly Language Tutorials - asmtutor.com 对于像"Hello world"这样的命令行程序,换行符时必不可少的. ...

  8. 计算机换行符号,计算机中的换行符、回车符、#92;n、#92;r、#92;n#92;r 怎么区分啊?...

    满意答案 水沁1436 2016.01.27 采纳率:45%    等级:7 已帮助:4310人 '\r'是回车,前者使光标到行首,(carriage return) '\n'是换行,后者使光标下移一 ...

  9. 微信公众帐号开发教程第7篇-文本消息中换行符的使用

    本篇文章主要介绍在文本消息中使用换行符的好处以及如何使用换行符. 最近一个月虽然抽不出时间写博客,但却一直在认真答复大家提出的问题.收到这么多的回复.关注和答谢,还是蛮有成就感的,让我觉得做这件事越来 ...

最新文章

  1. Android 性能分析工具dumpsys的使用(自己增加一部分在后面)
  2. Knative 实践:从源代码到服务的自动化部署
  3. questions for the exploitation of technologies
  4. C++ new delete(二)
  5. php程序yii是什么意思,Yii框架啥意思
  6. How To Install Visual Studio Code On Ubuntu
  7. Solidworks如何自动打开和关闭特征识别FeatureWorks
  8. visual studio 判断dropdownlist选的是什么_测试:选一顶你觉得最漂亮的皇冠。测你长了张什么脸?我是发财脸...
  9. MySQL镜像下载及启动
  10. Atititt hi dev eff db op Spring JDBC 目录 1. Spring JDBC 2 1 1.1. Atitit 数据库db insert 插入数据data 最佳实践
  11. 强制卸载kernel
  12. 高通工具QXDM安装及使用方法
  13. 局域网架设 NOD 32 镜像更新服务器
  14. 使用CSS更改hr标签的厚度
  15. 《精英日课》第三季_2019年四月新书《九个工作谎言》_1工作是具体的,公司是虚拟的
  16. android 水波纹扩散动画,[Android]多层波纹扩散动画——自定义View绘制
  17. 2022年你应该知道的十大Python库
  18. 为什么很多Java程序员都转行做大数据了?
  19. 根目录磁盘空间不足,使用fdisk添加新磁盘问题
  20. C++:后缀增量和减量运算符:++ 和 --

热门文章

  1. brad wu_一百万归功于Brad Traversy
  2. 无导师学习_如何找到一位导师并加快学习速度:新手指南。
  3. javascript 堆栈_JavaScript调用堆栈-它是什么以及为什么它是必需的
  4. 学java为什么要报java培训班?
  5. flume源码学习8-hdfs sink的具体写入流程
  6. EnterLib PIAB又一个BUG?
  7. PHPExcel使用-使用PHPExcel导出文件-导出MySQL数据
  8. PgSQL · 特性分析 · full page write 机制
  9. 【BZOJ】3542: DZY Loves March
  10. Apache2.4+Tomcat7集群搭建