文档章节

netty 学习 (1)

yaokangjun
 yaokangjun
发布于 2014/06/04 15:00
字数 934
阅读 2639
收藏 7
点赞 2
评论 5
Server与Client建立连接后,会执行以下的步骤:
1、Client向Server发送消息:Are you ok?
2、Server接收客户端发送的消息,并打印出来。
3、Server端向客户端发送消息:I am ok!
4、Client接收Server端发送的消息,并打印出来,通讯结束。

涉及到的类有4个:
1、HelloServer :server类,启动Netty server
2、HelloServerInHandler:server的handler,接收客户端消息,并向客户端发送消息
3、HelloClient:client类,建立于Netty server的连接

4、HelloClientIntHandler:client的handler,接收server端的消息,并向服务端发送消息

一、先加入必要的类库:

二、HelloServer代码如下:

package com.yao.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class HelloServer {
	public void start(int port) throws Exception {
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						public void initChannel(SocketChannel ch)
								throws Exception {
							// 注册handler
							ch.pipeline().addLast(new HelloServerInHandler());
						}
					}).option(ChannelOption.SO_BACKLOG, 128)
					.childOption(ChannelOption.SO_KEEPALIVE, true);

			ChannelFuture f = b.bind(port).sync();

			f.channel().closeFuture().sync();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws Exception {
		HelloServer server = new HelloServer();
		server.start(8000);
	}
}
三、 HelloServerInHandler代码如下:
package com.yao.netty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// 该handler是InboundHandler类型
public class HelloServerInHandler extends ChannelInboundHandlerAdapter {
	private static Log logger = LogFactory.getLog(HelloServerInHandler.class);

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		logger.info("HelloServerInHandler.channelRead");
		ByteBuf result = (ByteBuf) msg;
		byte[] result1 = new byte[result.readableBytes()];
		// msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中
		result.readBytes(result1);
		String resultStr = new String(result1);
		// 接收并打印客户端的信息
		System.out.println("Client said:" + resultStr);
		// 释放资源,这行很关键
		result.release();

		// 向客户端发送消息
		String response = "I am ok!";
		// 在当前场景下,发送的数据必须转换成ByteBuf数组
		ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
		encoded.writeBytes(response.getBytes());
		ctx.write(encoded);
		ctx.flush();
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
}
四、HelloClient代码如下:


package com.yao.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class HelloClient {
	public void connect(String host, int port) throws Exception {
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {
			Bootstrap b = new Bootstrap();
			b.group(workerGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true)
			.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new HelloClientIntHandler());
				}
			});

			// Start the client.
			ChannelFuture f = b.connect(host, port).sync();

			// Wait until the connection is closed.
			f.channel().closeFuture().sync();
		} finally {
			workerGroup.shutdownGracefully();
		}

	}

	public static void main(String[] args) throws Exception {
		HelloClient client = new HelloClient();
		client.connect("127.0.0.1", 8000);
	}
}
五、 HelloClientIntHandler代码如下:

package com.yao.netty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class HelloClientIntHandler extends ChannelInboundHandlerAdapter {
	private static Log logger = LogFactory.getLog(HelloClientIntHandler.class);

	// 接收server端的消息,并打印出来
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		logger.info("HelloClientIntHandler.channelRead");
		ByteBuf result = (ByteBuf) msg;
		byte[] result1 = new byte[result.readableBytes()];
		result.readBytes(result1);
		System.out.println("Server said:" + new String(result1));
		result.release();
	}

	// 连接成功后,向server发送消息
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.info("HelloClientIntHandler.channelActive");
		String msg = "Are you ok?";
		ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
		encoded.writeBytes(msg.getBytes());
		ctx.write(encoded);
		ctx.flush();
	}
}
六、还有log4j.xml文件:

<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5p] [%d] [%t] [%c] %m%n"/>
        </layout>
    </appender>
    
    <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="./log/netty.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5p] [%d] [%t] [%c] %m%n"/>
        </layout>
    </appender>
    
    <appender name="FILE_ERR" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="./log/netty_err.log"/>
        <param name="Threshold" value="ERROR" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5p] [%d] [%t] [%c] %m%n"/>
        </layout>
    </appender>	    
    
	<logger name="io.netty" additivity="false">
		<level value="INFO,DEBUG" />
		<appender-ref ref="FILE" />
		<appender-ref ref="FILE_ERR" />
		<appender-ref ref="CONSOLE" />
	</logger>
	<logger name="com.yao" additivity="false">
		<level value="INFO,DEBUG" />
		<appender-ref ref="FILE" />
		<appender-ref ref="FILE_ERR" />
		<appender-ref ref="CONSOLE" />
	</logger>
    
    <root>
    	
      <level value="debug"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE_ERR" />
    </root>

</log4j:configuration>
总结:
通过上面简单的实例可以发现:
1、在没有任何encoder、decoder的情况下,Netty发送接收数据都是按照ByteBuf的形式,其它形式都是不合法的。
2、接收发送数据操作都是通过handler实现的,handler在netty中占据了非常重要的位置。
3、netty的handler是基于事件触发的,例如当client连接server成功后,client中的HelloClientIntHandler的channelActive方法会自动调用。

© 著作权归作者所有

共有 人打赏支持
yaokangjun
粉丝 26
博文 62
码字总数 29408
作品 0
广州
程序员
加载中

评论(5)

sumyfly
sumyfly

引用来自“kstyle2”的评论

有没有派生于ChannelOutboundHandlerAdapter
获得了ChannelHandlerContext就可发送了,可以自己写一个函数
k
kstyle2
有没有派生于ChannelOutboundHandlerAdapter
k
kstyle2
我想问一下netty客户端动态地构造要发送的消息,该如何做?
因为,我看了网上几乎所有的例子都是基于ChannelInboundHandlerAapter.
yaokangjun
yaokangjun

引用来自“-亮子-”的评论

netty的版本号是?
4.0.17
-亮子-
-亮子-
netty的版本号是?
NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo。服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了。同时...

JackJiang-
2016/06/28
547
0
NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

前言 NIO框架的流行,使得开发大并发、高性能的互联网服务端成为可能。这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2、而Netty的主要版本是Netty3和Netty4(Netty5已经被...

JackJiang-
2016/06/24
349
0
Android与MINA2、Netty4的跨平台UDP双向通信实战

概述 本文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo。 当前由于NIO框架的流行,使得开发大并发、高性能的互联网服务端成为可能。...

JackJiang-
2016/06/30
751
1
源码之下无秘密 ── 做最好的 Netty 源码分析教程

背景 在工作中, 虽然我经常使用到 Netty 库, 但是很多时候对 Netty 的一些概念还是处于知其然, 不知其所以然的状态, 因此就萌生了学习 Netty 源码的想法. 刚开始看源码的时候, 自然是比较痛苦...

永顺
2017/11/29
0
0
如何系统学习新技术?

最近想学习一下netty,或者mina , 但是不知道如何学习,以前学三大框架或者android,有大量的书籍或者培训机构放出来的视频,学习起来方便。 但是比如netty,好像就看到有一本书,mina则没有...

plugin
2015/01/03
267
2
《深入探索Netty原理及源码分析》文集小结

写在2017年末尾,翻看文集的第一篇文章已经是三个月前的事了,也没想过这文集会写那么久,这么慢。。。 Netty文集中的文章主要都是我学习过程的笔记,写博客的主要目的是为了通过输出来倒逼输...

tomas家的小拨浪鼓
2017/12/30
0
0
MyMVC 0.2发布

#为什么开发MyMVC 希望借助于Netty强大的NIO能力来打造一款轻量级、性能高的HTTP MVC 服务器。 同时,并不会屏蔽技术原理,使得用户知其然且知其所以然。 #MyMVC的技术方案 网络IO框架: Net...

强子哥哥
2016/05/21
91
2
MyMVC 0.2 发布

#为什么开发MyMVC 希望借助于Netty强大的NIO能力来打造一款轻量级、性能高的HTTP服务器。 同时,并不会屏蔽技术原理,使得用户知其然且知其所以然。 FAFAFA;"> 网络IO框架: Netty URL映射方案...

强子哥哥
2016/05/21
2.5K
16
强子哥哥/MyMVC

#为什么开发MyMVC 希望借助于Netty强大的NIO能力来打造一款轻量级、性能高的HTTP服务器。 同时,并不会屏蔽技术原理,使得用户知其然且知其所以然。 #MyMVC的技术方案 网络IO框架: Netty URL...

强子哥哥
2016/05/17
0
0
Netty高性能架构的理解之道

Netty的简单介绍 Netty 是一个 NIO client-server(客户端服务器)框架,使用 Netty 可以快速开发网络应用,例如服务器和客户 端协议。 Netty 提供了一种新的方式来使开发网络应用程序,这种新...

烂猪皮
05/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

与女儿谈商业模式 (5):糖果连锁店?

分类:与女儿谈商业模式 2007-08-02 15:27阅读(8394)评论(32)   与女儿谈商业模式(5):糖果连锁店?   陈志武 /文   谈过星巴克、沃尔玛、戴尔以及微软的故事后,给陈笛印象最深的莫...

祖冲之
1分钟前
0
0
Linux平台下RMAN异机恢复总结

潇湘隐者 Linux平台下RMAN异机恢复总结 2017-05-29 16:30 by 潇湘隐者, ... 阅读, ... 评论, 收藏, 编辑 下面总结、整理一下RMAN异机恢复这方面的知识点,这篇笔记在个人笔记里面躺了几年了,...

rootliu
9分钟前
0
0
Spring配置xml启动报错 Connot find 'beans'

1.我们先看一下spring的原始配置 <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSc......

江湖鱼大虾
11分钟前
0
0
www.w3.org被qiang导致logback报错:Connect reset

web项目部署到tomcat后,web项目中的logback不能运行,报错信息如下: Reported exception: ch.qos.logback.core.joran.spi.JoranException: I/O error occurred while parsing xml file......

浮躁的码农
34分钟前
0
0
JDeveloper中文乱码解决

全局设置字体; 全局设置环境编码; 项目设置编译器环境编码。

wffger
今天
2
0
MySQL主从介绍 , 准备工作,配置主,配置从, 测试主从同步

MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的 MySQL主从是基于binlog的,主上须开启bin...

TaoXu
今天
2
0
线性代数学习总结

亭子happy
今天
1
0
Java8:Lambda表达式增强版Comparator和排序

1、概述 在这篇教程里,我们将要去了解下即将到来的JDK 8(译注,现在JDK 8已经发布了)中的Lambda表达式——特别是怎样使用它来编写Comparator和对集合(Collection)进行排序。 这篇文章是...

孟飞阳
今天
0
0
从架构到组件,深挖istio如何连接、管理和保护微服务2.0?

近几年我一直从事于微服务系统的设计以及实现方面的工作,属于微服务架构一线实践者。之前做过一些单体系统的微服务改造,在微服务拆分、治理等方面都有一定的经验。 本人比较特殊一点的经历...

xiaomin0322
今天
1
0
基于vue的h5文件切片上传(获取文件md5,实现秒传、进度条实现)

template <button @click="file"></button><label ref="upload" style="position: relative;"> <input type="file" @change="selectFile" style="position: abs......

hkaikai
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部