摘要

本文是学习Netty的第一篇文章,主要对Netty的Server和Client间的通讯机制进行验证。

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;

importio.netty.bootstrap.ServerBootstrap;

importio.netty.channel.ChannelFuture;

importio.netty.channel.ChannelInitializer;

importio.netty.channel.ChannelOption;

importio.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

importio.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioServerSocketChannel;

publicclassHelloServer {

publicvoidstart(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(newChannelInitializer<SocketChannel>() {

@Override

publicvoidinitChannel(SocketChannel ch)

throws Exception {

// 注册handler

ch.pipeline().addLast(newHelloServerInHandler());

}

}).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();

}

}

publicstaticvoidmain(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;

importorg.apache.commons.logging.Log;

importorg.apache.commons.logging.LogFactory;

// 该handler是InboundHandler类型

public class HelloServerInHandlerextends ChannelInboundHandlerAdapter {

private static Log logger = LogFactory.getLog(HelloServerInHandler.class);

@Override

public void channelRead(ChannelHandlerContextctx, 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(ChannelHandlerContextctx) throws Exception {

ctx.flush();

}

}

四、HelloClient代码如下:

package com.yao.netty;

importio.netty.bootstrap.Bootstrap;

importio.netty.channel.ChannelFuture;

importio.netty.channel.ChannelInitializer;

importio.netty.channel.ChannelOption;

importio.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioSocketChannel;

publicclassHelloClient {

publicvoidconnect(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(newChannelInitializer<SocketChannel>() {

@Override

publicvoidinitChannel(SocketChannel ch) throws Exception {

ch.pipeline().addLast(newHelloClientIntHandler());

}

});

// Start the client.

ChannelFuture f = b.connect(host,port).sync();

// Wait until the connection isclosed.

f.channel().closeFuture().sync();

} finally {

workerGroup.shutdownGracefully();

}

}

publicstaticvoidmain(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;

importorg.apache.commons.logging.Log;

importorg.apache.commons.logging.LogFactory;

public class HelloClientIntHandlerextends ChannelInboundHandlerAdapter {

private static Log logger = LogFactory.getLog(HelloClientIntHandler.class);

// 接收server端的消息,并打印出来

@Override

public void channelRead(ChannelHandlerContextctx, Object msg) throws Exception {

logger.info("HelloClientIntHandler.channelRead");

ByteBufresult = (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(ChannelHandlerContextctx) 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"?>

<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">

<log4j:configurationxmlns: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-refref="FILE" />

<appender-refref="FILE_ERR" />

<appender-refref="CONSOLE" />

</logger>

<logger name="com.yao" additivity="false">

<level value="INFO,DEBUG" />

<appender-refref="FILE" />

<appender-refref="FILE_ERR" />

<appender-refref="CONSOLE" />

</logger>

<root>

<level value="debug"/>

<appender-refref="FILE"/>

<appender-refref="CONSOLE"/>

<appender-refref="FILE_ERR" />

</root>

</log4j:configuration>

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

netty 学习 (1)相关推荐

  1. Netty学习笔记(二) 实现服务端和客户端

    在Netty学习笔记(一) 实现DISCARD服务中,我们使用Netty和Python实现了简单的丢弃DISCARD服务,这篇,我们使用Netty实现服务端和客户端交互的需求. 前置工作 开发环境 J ...

  2. Netty 学习和进阶策略

    https://www.infoq.cn/article/xt9*7K4fJktiuWTLYrZS 背景 Netty 框架的特点 Netty 的一个特点就是入门相对比较容易,但是真正掌握并精通是非常困 ...

  3. Netty学习笔记(六)Pipeline的传播机制

    前面简单提到了下Pipeline的传播机制,这里再详细分析下 Pipeline的传播机制中有两个非常重要的属性inbound和outbound(AbstractChannelHandlerContex ...

  4. Netty学习笔记(二)Netty服务端流程启动分析

    先贴下在NIO和Netty里启动服务端的代码 public class NioServer { /*** 指定端口号启动服务* */public boolean startServer(int por ...

  5. Netty学习开发之路

    Netty学习 前言简介 ======= 我们公司最近决定做个基于netty tcp的IM程序,由于最近项目比较紧张,所以没办法,只能我和另外一个做安卓的同事一起学习开发.在这里先说一句瓜皮呦!而且项 ...

  6. 1、张龙netty学习 第一个netty服务端

    张龙netty学习 第一个netty服务端 public class TestServer {public static void main(String[] args) throws Excepti ...

  7. 04、Netty学习笔记—(黏包半包及协议设计解析)

    文章目录 一.粘包与半包 1.1.现象分析 1.1.1.粘包.半包情况分析 1.1.2.滑动窗口.MSS限制.Nagle算法介绍 1.2.粘包.半包现象复现 1.2.1.粘包复现 1.2.2.半包复现 ...

  8. Netty学习(一):初识Netty

    章节 1.Netty学习(一):初识Netty 2.Netty学习(二):Netty的核心组件 3.Netty学习(三):Netty的流程分析 4.Netty学习(四):Netty零拷贝(转载) 5. ...

  9. Netty学习笔记:二、NIO网络应用实例-群聊系统

    实例要求: 编写一个NIO群聊系统,实现服务器端和多个客户端之间的数据简单通讯(非阻塞): 实现多人群聊: 服务器端:可以监测用户上线.离线,并实现消息转发功能: 客户端:通过channel可以无阻塞 ...

  10. Netty,Tcp,socket的java框架,netty学习

    最新更新,报文发送,机器终端(车)与服务端 先学习一下基本内容,以下是基于基本内容 互相转换:byte(字节,字节是数字单位,他的数组是十进制内容),bit(二进制内容,不用操心这部分),十六进制0x ...

最新文章

  1. 深度学总结:skip-gram pytorch实现
  2. java进出栈_JVM函数调用:Java出入栈
  3. BUUCTF-WEB:[HCTF 2018]WarmUp
  4. 使用xUnit为.net core程序进行单元测试(中)
  5. DB2常用傻瓜问题1000问(之一)
  6. java biginteger 比较大小,java – 打印非常大的BigIntegers
  7. 2022蓝骑士发展与保障报告
  8. 用python计算1~100的阶乘之和_在Python中递归函数调用举例and匿名函数lambda求1~100的和及计算阶乘举例...
  9. 怎么用html做随机颜色,JavaScript 实现网站标签随机颜色的方法
  10. js中filter函数
  11. 如何在PPT中制作动态图表,学会这种方法实在太简单
  12. 软考计算机英语词汇,软考计算机专业英语常用词汇(首字母I-O)
  13. vue打包时页面布局出现混乱
  14. Mysql修改服务中可执行文件路径
  15. php 发socket数据库,php socket连接数据库
  16. Centos下安装桌面环境和Flash插件
  17. LED驱动电源EMI整改方案
  18. 知识图谱核心技术(一):知识图谱的概述
  19. Windows常用的快捷键 让妹子办公效率速提升
  20. 中国IT领袖峰会 以5G与人工智能为主题

热门文章

  1. javaweb文件压缩下载
  2. vue中keep-alive缓存功能使用详解
  3. Centos下安装nginx步骤解析
  4. caffe 训练solver配置
  5. 2019年春季学习第七周学习总结
  6. 大型架构之科普工具篇
  7. 滴滴passport设计之道:帐号体系高可用的7条经验
  8. c#过滤字符串中相同的字符串只保留一个
  9. 我的电脑缩略图模式盘符名字不见了
  10. Ubuntu使用技巧集锦(持续追加中……)