mina、netty消息边界问题(采用换行符)
在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
mina、netty消息边界问题(采用换行符)的更多相关文章
- linux与windows回车换行符的区别
转自:http://www.cnblogs.com/dartagnan/archive/2010/12/14/2003499.html “回车”(carriage return)VS “换行”(li ...
- 换行符\r \n LF
前言:在对照PSR-2规范时,看到文件结尾必须要以Unix LF(linefeed)结尾,不懂查~ 来源于:http://www.cppblog.com/prayer/archive/2009/08/ ...
- c++ 关于换行符
windows: \r\n linux: \n mac: \r http://blog.chinaunix.net/uid-12706763-id-10830.html 不同的OS有不同的换行符: O ...
- 计算机中的换行符、回车符、\n、\r、\n\r 怎么区分啊?
'\r'是回车,前者使光标到行首,(carriage return)'\n'是换行,后者使光标下移一格,(line feed) \r 是回车,return\n 是换行,newline对于换行这个动作, ...
- 换行符 \r \n \r\n 在不同系统下的区别
'\r'是回车,前者使光标到行首,(carriage return)'\n'是换行,后者使光标下移一格,(line feed)\r 是回车,return\n 是换行,newline对于换行这个动作,u ...
- Linux、Windows 和 Mac 中的换行符对比
原文地址:Linux.Windows 和 Mac 中的换行符对比 博客地址:http://www.moonxy.com 一.前言 经常使用 Window.Linux 等不同操作系统的开发者,在处理文本 ...
- Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息
在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...
- Visual Studio error C2001:常量中有换行符(解决办法)
在Visual Studio自动生成的项目中,碰见了一件关于文件编码的问题,集中在类似于以下的语句上: DASLog (DASProtWarn, L"(%s)消息超时,进入慢循环召唤模式.& ...
- [转]Java中的回车换行符/n /r /t
'\r'是回车,'\n'是换行,前者使光标到行首,后者使光标下移一格.通常用的Enter是两个加起来.下面转一篇文章. 回车和换行 今天,我总算搞清楚"回车"(carriage r ...
随机推荐
- c++中参数传递和函数返回简析
1.参数传递: 每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参.形参的初始化与变量的初始化一样. 非引用类型:如果形参具有非引用类型,则复制实参的值.普通的非引用类 ...
- 自适应Cell
// // ViewController.m // 04-自适应cell // // Created by
- mysql安装常见问题(系统找不到指定的文件、发生系统错误 1067 进程意外终止)
在安装mysql时总是会遇到这样那样的问题,每次重新安装都会花很多时间来排查.在网上其实有很多相关的文章,但很多都只讲了方法,但没讲具体细节问题,导致无法解决问题.其实有时候知道问题的原因,但总是因为 ...
- doGet与doPost的区别
转自:http://blog.csdn.net/luoweifu/article/details/7865243 目录(?)[-] 不同点一 不同点二 输入表单inputhtml Serlvlet ...
- 如何在Eclipse中开发并调试自己的插件(或者说如何将自己的代码插件化)
Setting up Eclipse to create and debug plugins for ImageJ 最近在做一个关于卫星遥感全链路仿真的项目,由于项目是基于ImageJ开发,而Imag ...
- php随笔2-php+ajax 实现输入读取数据库显示匹配信息
dropbox_index.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- vb listview 的常用操作
常用操作:获取当前行数和列数: MsgBox "行数:" & ListView1.ListItems.Count & "列数:" & L ...
- MVC4,MVC3,VS2012+ entity framework Migration from Sqlserver to Mysql
在开发的初期个人认为因VS与Sqlserver的配合很默契,即可以方便的实现Code First,又可以使用SqlServer Manager很漂亮的进行建模与变更,也许是个人的使用习惯MS的界面做的 ...
- 升级linux内核(2.6.32->3.10.81),安装docker
1.内核升级环境准备 #查看已经安装的和未安装的软件包组,来判断我们是否安装了相应的开发环境和开发库: yum grouplist #一般是安装这两个软件包组,这样做会确定你拥有编译时所需的一切工具 ...
- 详细比较三个 CSS 预处理器(框架):Sass、LESS 和 Stylus
[大伽说]如何运维千台云服务器 » CSS 预处理器技术已经非常的成熟,而且也涌现出了越来越多的 CSS 的预处理器框架.本文向你介绍使用最为普遍的三款 CSS 预处理器框架,分别是 Sass.L ...