文档章节

netty 学习 (1)

yaokangjun
 yaokangjun
发布于 2014/06/04 15:00
字数 934
阅读 2702
收藏 7
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的版本号是?
Netty 入门与实战:仿写微信 IM 即时通讯系统

被小伙伴日常催更了一个多月的 Netty 小册终于和大伙正式见面了,为了答谢小伙伴对小册的厚爱,我将赠送15个免费阅读小册的兑换码。 有两种方式可以获取免费兑换码: 1. 在本篇文章后面留言:...

闪电侠的博客
09/26
0
0
架构师必备技能之Netty 高并发 UTS 项目实战

一、Netty Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty 是一个基...

A尚学堂Nancy老师
08/27
0
0
强子哥哥/MyMVC

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

强子哥哥
2016/05/17
0
0
源码之下无秘密 ── 做最好的 Netty 源码分析教程

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

永顺
2017/11/29
0
0
针对(APP|浏览器)交互的HTTP服务器--MyMVC

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

强子哥哥
2016/05/18
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

linux脚本中父shell与子shell 执行的几种方式

本文主要介绍以下几个命令的区别: shell subshell source $ (commond) `commond` Linux执行Scripts有两种方式,主要区别在于是否建立subshell 1. source filename or . filename 不创建sub...

问题终结者
7分钟前
0
0
git简单操作

1、 git init 初始化仓库 git add 1.txt 添加文件 git commit -m ”commit” 提交更新,添加注释 git status 查看仓库状态 git log 查看日志 //修改文件后提交更新 git diff 查看有哪些修改 ...

xiaobai1315
11分钟前
0
0
基于vue的Element-ui定义自己的select组件

基于vue的Element-ui定义自己的select组件 <template> <div> <el-select v-model="svalue" placeholder="请选择" filterable> <el-option v-for="item in options"......

莫沫达
13分钟前
0
0
对象检测(object detection)算法图解

摘要: 本文简要介绍图像检测中常用的深度学习方法——RCNN家族系列算法,以图像讲解形式,便于理解。 在生活中,经常会遇到这样的一种情况,上班要出门的时候,突然找不到一件东西了,比如钥...

阿里云官方博客
15分钟前
0
0
计算机通信协议学习-Http

HTTP协议: 引用:http://www.cnblogs.com/ranyonsue/p/5984001.html HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网( WWW:World Wide Web)服务...

xiaoyaoyoufang
18分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部