Java NIO框架Netty教程(三) 字符串消息收发(转)

news/2024/7/15 16:49:41 标签: java, netty, python

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

了解了Netty的基本概念(http://www.it165.net/pro/html/201207/3173.html),开发起来应该会顺手很多。 在“Hello World(http://www.it165.net/pro/html/201207/3142.html)”代码中,我们只是在完成绑定的时候,在各自的本地打印了简单的信息,并没有客户端和服务端的消息传递。这个肯定是最基本的功能。在上代码之前,先补充一个Netty中重要的概念,ChannelBuffer.


ChannelBuffer



 

 

Netty中的消息传递,都必须以字节的形式,以ChannelBuffer为载体传递。简单的说,就是你想直接写个字符串过去,对不起,抛异常。虽然,Netty定义的writer的接口参数是Object的,这可能也是会给新上手的朋友容易造成误会的地方。Netty源码中,是这样判断的:

Java代码    收藏代码
  1.   SendBuffer acquire(Object message) {  
  2.   
  3. if (message instanceof ChannelBuffer) {  
  4.   
  5. return acquire((ChannelBuffer) message);  
  6.   
  7. else if (message instanceof FileRegion) {  
  8.   
  9. return acquire((FileRegion) message);  
  10.   
  11. }  
  12.   
  13.    
  14.   
  15. throw new IllegalArgumentException(  
  16.   
  17. "unsupported message type: " + message.getClass());  
  18.   
  19. }  

 所以,我们要想传递字符串,那么就必须转换成ChannelBuffer。明确了这一点,接下来我们上代码:

 

Java代码    收藏代码
  1. /** 
  2.  
  3. * @author lihzh 
  4.  
  5. * @alia OneCoder 
  6.  
  7. * @blog http://www.coderli.com 
  8.  
  9. */  
  10.   
  11. public class MessageServer {  
  12.   
  13.    
  14.   
  15. public static void main(String args[]) {  
  16.   
  17. // Server服务启动器  
  18.   
  19. ServerBootstrap bootstrap = new ServerBootstrap(  
  20.   
  21. new NioServerSocketChannelFactory(  
  22.   
  23. Executors.newCachedThreadPool(),  
  24.   
  25. Executors.newCachedThreadPool()));  
  26.   
  27. // 设置一个处理客户端消息和各种消息事件的类(Handler)  
  28.   
  29. bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  30.   
  31. @Override  
  32.   
  33. public ChannelPipeline getPipeline() throws Exception {  
  34.   
  35. return Channels.pipeline(new MessageServerHandler());  
  36.   
  37. }  
  38.   
  39. });  
  40.   
  41. // 开放8000端口供客户端访问。  
  42.   
  43. bootstrap.bind(new InetSocketAddress(8000));  
  44.   
  45. }  
  46.   
  47.    
  48.   
  49. private static class MessageServerHandler extends SimpleChannelHandler {  
  50.   
  51.    
  52.   
  53. /** 
  54.  
  55. * 用户接受客户端发来的消息,在有客户端消息到达时触发 
  56.  
  57. * 
  58.  
  59. * @author lihzh 
  60.  
  61. * @alia OneCoder 
  62.  
  63. */  
  64.   
  65. @Override  
  66.   
  67. public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {  
  68.   
  69. ChannelBuffer buffer = (ChannelBuffer) e.getMessage();  
  70.   
  71. System.out.println(buffer.toString(Charset.defaultCharset()));  
  72.   
  73. }  
  74.   
  75.    
  76.   
  77. }  
  78.   
  79. }  
  80.   
  81. /** 
  82.  
  83. * @author lihzh 
  84.  
  85. * @alia OneCoder 
  86.  
  87. * @blog http://www.coderli.com 
  88.  
  89. */  
  90.   
  91. public class MessageClient {  
  92.   
  93.    
  94.   
  95. public static void main(String args[]) {  
  96.   
  97. // Client服务启动器  
  98.   
  99. ClientBootstrap bootstrap = new ClientBootstrap(  
  100.   
  101. new NioClientSocketChannelFactory(  
  102.   
  103. Executors.newCachedThreadPool(),  
  104.   
  105. Executors.newCachedThreadPool()));  
  106.   
  107. // 设置一个处理服务端消息和各种消息事件的类(Handler)  
  108.   
  109. bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  110.   
  111. @Override  
  112.   
  113. public ChannelPipeline getPipeline() throws Exception {  
  114.   
  115. return Channels.pipeline(new MessageClientHandler());  
  116.   
  117. }  
  118.   
  119. });  
  120.   
  121. // 连接到本地的8000端口的服务端  
  122.   
  123. bootstrap.connect(new InetSocketAddress("127.0.0.1"8000));  
  124.   
  125. }  
  126.   
  127.    
  128.   
  129. private static class MessageClientHandler extends SimpleChannelHandler {  
  130.   
  131.    
  132.   
  133. /** 
  134.  
  135. * 当绑定到服务端的时候触发,给服务端发消息。 
  136.  
  137. * 
  138.  
  139. * @alia OneCoder 
  140.  
  141. * @author lihzh 
  142.  
  143. */  
  144.   
  145. @Override  
  146.   
  147. public void channelConnected(ChannelHandlerContext ctx,  
  148.   
  149. ChannelStateEvent e) {  
  150.   
  151. // 将字符串,构造成ChannelBuffer,传递给服务端  
  152.   
  153. String msg = "Hello, I'm client.";  
  154.   
  155. ChannelBuffer buffer = ChannelBuffers.buffer(msg.length());  
  156.   
  157. buffer.writeBytes(msg.getBytes());  
  158.   
  159. e.getChannel().write(buffer);  
  160.   
  161. }  
  162.   
  163. }  
  164.   
  165.    
  166.   
  167. }  

 

与 “Hello World(http://www.it165.net/pro/html/201207/3142.html)” 样例代码不同的是,客户端在channel连通后,不是在本地打印,而是将消息转换成ChannelBuffer传递给服务端,服务端接受到ChannelBuffer后,解码成字符串打印出来。


同时,通过对比可以发现,变动的只是Handler里的代码,启动服务和绑定服务的代码没有变化,也就是我们在概念介绍里提到了,关注Handler,在Handler里处理我们自己的业务。所以,以后我们会只给出业务中关键代码,不会在上重复的代码:)

由于在Netty中消息的收发全依赖于ChannelBuffer,所以,下一章我们将会详细的介绍ChannelBuffer的使用。我们一起学习。

转载于:https://my.oschina.net/yearnfar/blog/151997


http://www.niftyadmin.cn/n/989886.html

相关文章

细说Redis监控和告警

https://blog.csdn.net/qq_27623337/article/details/53206685

Python全栈工程师(数值类型、运算符)

ParisGabriel Python 入门基础python的应用领域:1.系统运维2.网络编程(如:网络爬虫,搜索引擎,服务器编程)3.科学计算4.航空领域(如:卫星,导弹,等)5.人工智能&…

Matlab eval不显示在命令行方法

Matlab eval不显示在命令行方法 写一个数据处理的程序,需要多个变量,使用eval函数,结果一直在下面输出结果,有点烦。 例如给h1,h2,h3,h4分别赋值1,2,3,4: for i 1:4eval(strcat(h,num2str(i),,num2str(i))); end输出…

PHPStorm下XDebug配置

1安装Xdebug 用yum安装可能会失败,用pecl安装成功。 #yum installphp-pecl-xdebug.x86_64 pecl installxdebug 如果pecl命令不存在请先安装php-pear 命令:yum install php-pear 注意多加了一项IDE Key,且要与后面PHPStorm中…

PAT --- 1082.射击比赛 (20 分)

1082 射击比赛 (20 分) 本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军;谁差得最远,谁就是菜鸟。本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟。我们假设靶心在…

ZAB协议简介

Zookeeper 使用 Zookeeper Atomic Broadcast (ZAB) 协议来保障分布式数据一致性。 ZAB是一种支持崩溃恢复的消息广播协议,采用类似2PC的广播模式保证正常运行时性能,并使用基于 Paxos 的策略保证崩溃恢复时的一致性。 在阅读本文前建议先了解2PC和Paxos …

调试日志——基于stm32的智能声光报警器(三)

智能声光报警器基本功能调试完成。 1.通过拨码开关来设置LED闪烁的频率。 2.关门时喇叭不想,灯熄灭。 3.旁路模式时,灯处于闪烁状态,此时关门灯扔闪烁。 关于此次代码我觉得还是有可以优化的地方,电源方案也还是可以再改变的更好。…

获取客户端网卡MAC地址和IP地址实现JS代码

2019独角兽企业重金招聘Python工程师标准>>> 在做B/S结构的系统时,常常需要获取客户端的一些信息,如IP和MAC,以结合身份验证。要获取服务器端的MAC很容易,但是要获取客户端的MAC的地址确要花费一翻心思,通常…