Netty入门——客户端与服务端通信
Netty简介
Netty是一个基于JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。Netty 已逐渐成为 Java NIO 编程的首选框架。
什么是物联网?
nio通信框架
物联网主要运用到netty哪些特性
a、TCP长连接
b、能够和各种序列化框架完美整合
为什么要使用netty,相对于其他通信框架mina有哪些优点
a、API使用简单,开发门槛低
b、功能强大,预置了多种编解码功能,支持多种主流协议
c、社区活跃,版本更新快
d、技术稳定可靠,如:elasticsearch、spark、dubbo、motan等开源框架底层通信采用的是netty
1、Netty服务端编写
首先,Netty通过ServerBootstrap启动服务端代码,需要四步:
第一步,定义两个线程组,用来处理客户端通道的accept和读写事件
第二步,绑定服务端通道NioServerSocketChannel
第三步,给读写事件的线程通道绑定handle,处理具体的业务逻辑
第四步,绑定监听
1.1、NettyServer——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;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters; /**
* Netty服务端编写
*
* @author Administrator
*
*/
public class NettyServer { public static void main(String[] args) throws InterruptedException {
// 首先,netty通过ServerBootstrap启动服务端
ServerBootstrap server = new ServerBootstrap();
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup =new NioEventLoopGroup();
//第1步定义两个线程组,用来处理客户端通道的accept和读写事件
//parentGroup用来处理accept事件,childgroup用来处理通道的读写事件
//parentGroup获取客户端连接,连接接收到之后再将连接转发给childgroup去处理
server.group(parentGroup, childGroup); //用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。
//用来初始化服务端可连接队列
//服务端处理客户端连接请求是按顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小。
server.option(ChannelOption.SO_BACKLOG, 128); //第2步绑定服务端通道
server.channel(NioServerSocketChannel.class); //第3步绑定handler,处理读写事件,ChannelInitializer是给通道初始化
server.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//解码器,接收的数据进行解码,一定要加在SimpleServerHandler 的上面
//maxFrameLength表示这一贞最大的大小
//delimiter表示分隔符,我们需要先将分割符写入到ByteBuf中,然后当做参数传入;
//需要注意的是,netty并没有提供一个DelimiterBasedFrameDecoder对应的编码器实现(笔者没有找到),因此在发送端需要自行编码添加分隔符,如 \r \n分隔符
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()[0]));
//把传过来的数据 转换成byteBuf
ch.pipeline().addLast(new SimpleServerHandler());
}
}); //第4步绑定8080端口
ChannelFuture future = server.bind(8080).sync();
//当通道关闭了,就继续往下走
future.channel().closeFuture().sync();
} }
1.2、SimpleServerHandler——处理客户端返回的数据
import java.nio.charset.Charset; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; /**
* 处理客户端返回的数据
*
* @author Administrator
*
*/
public class SimpleServerHandler extends ChannelInboundHandlerAdapter { /**
* 读取客户端通道的数据
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//可以在这里面写一套类似SpringMVC的框架
//让SimpleServerHandler不跟任何业务有关,可以封装一套框架
if(msg instanceof ByteBuf){
System.out.println(((ByteBuf)msg).toString(Charset.defaultCharset()));
} //业务逻辑代码处理框架。。。 //返回给客户端的数据,告诉我已经读到你的数据了
String result = "hello client ";
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(result.getBytes());
ctx.channel().writeAndFlush(buf); ByteBuf buf2 = Unpooled.buffer();
buf2.writeBytes("\r\n".getBytes());
ctx.channel().writeAndFlush(buf2);
System.out.println("==========");
} }
//使用下面命令测试上面代码。
1.开启上面main方法。
2.执行一下命令
c:>telnet localhost 8080
随便输入,会发现eclipse控制台会监听到输入的内容,有个问题接收时一个字一个字接受,可以让他一行一行接收
2、netty客户端编写
第一步,连接到服务端
第二步,向服务端发送数据
第三步,处理服务端返回的数据
第四步,关闭连接
2.1、NettyClient——Netty客户端编写
import com.alibaba.fastjson.JSONObject;
import com.dxfx.user.model.User; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.AttributeKey; /**
* Netty客户端编写
* @author Administrator
*
*/
public class NettyClient { public static void main(String[] args) throws InterruptedException {
// 首先,netty通过ServerBootstrap启动服务端
Bootstrap client = new Bootstrap(); //第1步 定义线程组,处理读写和链接事件,没有了accept事件
EventLoopGroup group = new NioEventLoopGroup();
client.group(group ); //第2步 绑定客户端通道
client.channel(NioSocketChannel.class); //第3步 给NIoSocketChannel初始化handler, 处理读写事件
client.handler(new ChannelInitializer<NioSocketChannel>() { //通道是NioSocketChannel
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
//字符串编码器,一定要加在SimpleClientHandler 的上面
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(
Integer.MAX_VALUE, Delimiters.lineDelimiter()[0]));
//找到他的管道 增加他的handler
ch.pipeline().addLast(new SimpleClientHandler());
}
}); //连接服务器
ChannelFuture future = client.connect("localhost", 8080).sync(); //发送数据给服务器
User user = new User();
user.setAge(12);
user.setId(1);
user.setName("sssss");
future.channel().writeAndFlush(JSONObject.toJSONString(user)+"\r\n"); for(int i=0;i<5;i++){
String msg = "ssss"+i+"\r\n";
future.channel().writeAndFlush(msg);
} //当通道关闭了,就继续往下走
future.channel().closeFuture().sync(); //接收服务端返回的数据
AttributeKey<String> key = AttributeKey.valueOf("ServerData");
Object result = future.channel().attr(key).get();
System.out.println(result.toString());
} }
2.2、SimpleClientHandler——处理服务端返回的数据
import java.nio.charset.Charset; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey; /**
* 处理服务端返回的数据
*
* @author Administrator
*
*/
public class SimpleClientHandler extends ChannelInboundHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
String value = ((ByteBuf) msg).toString(Charset.defaultCharset());
System.out.println("服务器端返回的数据:" + value);
} AttributeKey<String> key = AttributeKey.valueOf("ServerData");
ctx.channel().attr(key).set("客户端处理完毕"); //把客户端的通道关闭
ctx.channel().close();
} }
3、netty服务端输出的信息
{"age":12,"id":1,"name":"sssss"}
==========
ssss0
==========
ssss1
==========
ssss2
==========
ssss3
==========
ssss4
==========
4、netty客户端输出的信息
服务器端返回的数据:hello client
客户端处理完毕
服务器端返回的数据:hello client
服务器端返回的数据:hello client
服务器端返回的数据:hello client
服务器端返回的数据:hello client
服务器端返回的数据:hello client
Netty入门——客户端与服务端通信的更多相关文章
- Netty实现客户端和服务端通信简单例子
Netty是建立在NIO基础之上,Netty在NIO之上又提供了更高层次的抽象. 在Netty里面,Accept连接可以使用单独的线程池去处理,读写操作又是另外的线程池来处理. Accept连接和读写 ...
- Netty入门之客户端与服务端通信(二)
Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
- Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信
Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...
- 基于开源SuperSocket实现客户端和服务端通信项目实战
一.课程介绍 本期带给大家分享的是基于SuperSocket的项目实战,阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何实现打通B/S与C/S网络通讯,如果您对本期的<基于开源Supe ...
- Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令.
Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令. 一丶socket套接字 什么是socket套接字: 专业理解: socket是应用层与TCP/IP ...
- netty-3.客户端与服务端通信
(原) 第三篇,客户端与服务端通信 以下例子逻辑: 如果客户端连上服务端,服务端控制台就显示,XXX个客户端地址连接上线. 第一个客户端连接成功后,客户端控制台不显示信息,再有其它客户端再连接上线,则 ...
- Python socket编程客户端与服务端通信
[本文出自天外归云的博客园] 目标:实现客户端与服务端的socket通信,消息传输. 客户端 客户端代码: from socket import socket,AF_INET,SOCK_STREAM ...
- 实验09——java基于TCP实现客户端与服务端通信
TCP通信 需要先创建连接 - 并且在创建连接的过程中 需要经过三次握手 底层通过 流 发送数据 数据没有大小限制 可靠的传输机制 - 丢包重发 包的顺序的 ...
- 二、网络编程-socket之TCP协议开发客户端和服务端通信
知识点:之前讲的udp协议传输数据是不安全的,不可靠不稳定的,tcp协议传输数据安全可靠,因为它们的通讯机制是不一样的.udp是用户数据报传输,也就是直接丢一个数据包给另外一个程序,就好比寄信给别人, ...
随机推荐
- vue修改端口号
vue修改端口号 默认端口号 修改端口号 重新启动项目 npm run dev
- python基础 (编码进阶,文件操作和深浅copy)
1.编码的进阶 字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码. 即先将其他编码的字符串解码(decode)成unicode,再从uni ...
- sql2012包含数据库,快速生成用户tsql脚本
今天太忙(下班时,发现一个考试网站的不算BUG的BUG,这个BUG刚好能让我找到想要的数据,现在正辛苦的编码中...) 不多说,今天的技术文章,简单一点,帖一段昨天写的SQL代码 用于SQL2012中 ...
- [TestNG] Eclipse/STS中两种安装TestNG的方法
Two Ways To Install TestNG in Eclipse/STS Today I install the newest Sprint Tool Suite and want to i ...
- Spring Boot 启动(二) Environment 加载
Spring Boot 启动(二) Environment 加载 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 上一节中 ...
- Win 10 安装手机驱动
直接上图,看图操作即可.
- 【APP测试(Android)】--客户端数据库
- [IBM][CLI Driver] SQL0270N 函数不受支持(原因码:"75")。 SQLSTATE=42997
db2 update dbm cfg using FEDERATED yes 与 自动维护 (AUTO_MAINT) = ON 自动数据库备份 (AUTO_DB_BACKUP) = OFF 自动表 ...
- 利用python监测linux上的服务(简单实现服务宕掉自动发送邮件)
python 这里用到了四个python 模块 : import time (时间模块) import re (正则模块) import socket (监测端口模块)import yagmail ( ...
- Selenium webdriver操作日历控件
一般的日期控件都是input标签下弹出来的,如果使用webdriver 去设置日期, 1. 定位到该input 2. 使用sendKeys 方法 比如:使用定位: driver.findElement ...