netty4----netty5的客户端和服务端
服务端:
package com.server; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
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.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; /**
* netty5版本服务端
*/
public class Server { public static void main(String[] args) {
//服务类
ServerBootstrap bootstrap = new ServerBootstrap(); //boss和worker, netty5不是线程池,而是事件循环组,里面包含线程池。
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup(); try {
//设置线程池
bootstrap.group(boss, worker);//boss用来监听端口的 //设置socket工厂、
bootstrap.channel(NioServerSocketChannel.class); //设置管道工厂
bootstrap.childHandler(new ChannelInitializer<Channel>() { @Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ServerHandler());
}
}); //netty3中对应设置如下
//bootstrap.setOption("backlog", 1024);
//bootstrap.setOption("tcpNoDelay", true);
//bootstrap.setOption("keepAlive", true);
//设置参数,TCP参数
bootstrap.option(ChannelOption.SO_BACKLOG, 2048);//serverSocketchannel的设置,链接缓冲池的大小。tcp的服务端是有队列的。队列保存2048个客户端。2048后面的连接是拒绝的。
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);//socketchannel的设置,维持链接的活跃,清除死链接
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);//socketchannel的设置,关闭延迟发送。发一包并不是马上发出去,而是积累到一定之后再发出去。 //绑定端口
ChannelFuture future = bootstrap.bind(10101); System.out.println("start"); //等待服务端关闭
future.channel().closeFuture().sync(); } catch (Exception e) {
e.printStackTrace();
} finally{
//释放资源
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
package com.server; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 服务端消息处理
*/
public class ServerHandler extends SimpleChannelInboundHandler<String> { @Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
ctx.channel().writeAndFlush("hi");
ctx.writeAndFlush("hi");
} /**
* 新客户端接入
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
} /**
* 客户端断开
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelInactive");
} /**
* 异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
} }
客户端:
package com.client; import java.io.BufferedReader;
import java.io.InputStreamReader; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
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.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; /**
* netty5版本的客户端
*/
public class Client { public static void main(String[] args) {
//服务类
Bootstrap bootstrap = new Bootstrap();
//worker
EventLoopGroup worker = new NioEventLoopGroup();//boss用来监听端口,这里只创建worker
try {
//设置线程池
bootstrap.group(worker);
//设置socket工厂、
bootstrap.channel(NioSocketChannel.class);
//设置管道
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
});
ChannelFuture connect = bootstrap.connect("127.0.0.1", 10101);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while(true){
System.out.println("请输入:");
String msg = bufferedReader.readLine();
connect.channel().writeAndFlush(msg);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
worker.shutdownGracefully();
}
}
}
package com.client; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 客户端消息处理
*/
public class ClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("客户端收到消息:"+msg);
} }
一个客户端启动多个连接:
package com.client; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
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.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; /**
多连接客户端,客户端保持一个连接不够,要保持多个连接。 线程池是有多个线程,每个线程里面有一个任务队列,线程run的时候会从任务队列取一个任务出来,执行任务的run方法,
队列里面没有任务就阻塞等待新的任务进来。 一个thread + 队列 == 一个单线程线程池 =====> 线程安全的,任务是线性串行执行的 对象池:首先初始化n个对象,把这些对象放入一个队列里面,需要对象的时候会出栈一个对象,有对象就出栈,使用完了归还对象池里面。
没有对象会阻塞等待有可用的对象。或者创建一个新的对象使用完之后归还线程池,归还的时候如果池子满了就销毁。
比如数据库连接池:使用完后要释放资源,就是把连接放回连接池里面。 对象组:首先初始化n个对象,把这些对象放入一个数组里面。使用的时候获取一个对象不移除,使用完之后不用归还。需要对象有并发的能力。 对象组:线程安全,不会产生阻塞效应
对象池:线程不安全,会产生阻塞效应
*/
public class MultClient { /**
* 服务类
*/
private Bootstrap bootstrap = new Bootstrap(); /**
* 会话,多个channel,
*/
private List<Channel> channels = new ArrayList<>(); /**
* 引用计数
*/
private final AtomicInteger index = new AtomicInteger(); /**
* 初始化
* @param count
*/
public void init(int count){ //worker
EventLoopGroup worker = new NioEventLoopGroup(); //设置线程池
bootstrap.group(worker); //设置socket工厂、
bootstrap.channel(NioSocketChannel.class); //设置管道
bootstrap.handler(new ChannelInitializer<Channel>() { @Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
}); for(int i=1; i<=count; i++){
ChannelFuture future = bootstrap.connect("192.168.0.103", 10101);
channels.add(future.channel());
}
} /**
* 获取会话
*/
public Channel nextChannel(){
return getFirstActiveChannel(0);
} private Channel getFirstActiveChannel(int count){
Channel channel = channels.get(Math.abs(index.getAndIncrement() % channels.size()));
if(!channel.isActive()){
//重连
reconnect(channel);
if(count >= channels.size()){
throw new RuntimeException("no can use channel");
}
return getFirstActiveChannel(count + 1);
}
return channel;
} /**
* 重连
* @param channel
*/
private void reconnect(Channel channel){
synchronized(channel){
if(channels.indexOf(channel) == -1){//已经重连过了
return ;
}
Channel newChannel = bootstrap.connect("192.168.0.103", 10101).channel();
channels.set(channels.indexOf(channel), newChannel);
}
}
}
package com.client; import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* 启动类
*/
public class Start { public static void main(String[] args) { MultClient client = new MultClient();
client.init(5);//初始化5个连接
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while(true){
try {
System.out.println("请输入:");
String msg = bufferedReader.readLine();
client.nextChannel().writeAndFlush(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
} }
netty4----netty5的客户端和服务端的更多相关文章
- Netty4 学习笔记之二:客户端与服务端心跳 demo
前言 在上一篇Netty demo 中,了解了Netty中的客户端和服务端之间的通信.这篇则介绍Netty中的心跳. 之前在Mina 中心跳的使用是通过继承 KeepAliveMessageFacto ...
- netty-4.客户端与服务端心跳
(原) 第四篇,客户端与服务端心跳 心跳事件有三种,读空闲,写空闲,读写空闲,定义在了IdleState枚举类中,分别为READER_IDLE,WRITER_IDLE,ALL_IDLE 服务端: ma ...
- java客户端与服务端交互通用处理 框架解析
一.综述 java 客户端与服务端交互过程中,采用NIO通讯是异步的,客户端基本采用同一处理范式,来进行同异步的调用处理. 处理模型有以下几个要素: 1. NIO发送消息后返回的Future 2. 每 ...
- java 从零开始手写 RPC (03) 如何实现客户端调用服务端?
说明 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 写完了客户端和服务端,那么如何实现客户端和服务端的 ...
- TCP学习之五:客户端、服务端异步传输字符串
参考学习张子阳大神的博客:http://www.cnblogs.com/JimmyZhang/category/101698.html 消息发送接口: 消息接收接口: 客户端: 服务端: 消息发送类: ...
- TCP学习之三:客户端、服务端同步传输字符串
参考学习张子阳大神的博客:http://www.cnblogs.com/JimmyZhang/category/101698.html 一个客户端.发送一条消息 客户端: 服务端: 注意:Networ ...
- 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)
当客户端向服务端传输特殊字符时报错,错误信息如下图:
- [Java]Hessian客户端和服务端代码例子
简要说明:这是一个比较简单的hessian客户端和服务端,主要实现从客户端发送指定的数据量到服务端,然后服务端在将接收到的数据原封不动返回到客户端.设计该hessian客户端和服务端的初衷是为了做一个 ...
- SignalR 实现web浏览器客户端与服务端的推送功能
SignalR 是一个集成的客户端与服务器库,基于浏览器的客户端和基于 ASP.NET 的服务器组件可以借助它来进行双向多步对话. 换句话说,该对话可不受限制地进行单个无状态请求/响应数据交换:它将继 ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通
4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...
随机推荐
- python 糗事百科实例
爬取糗事百科段子,假设页面的URL是 http://www.qiushibaike.com/8hr/page/1 要求: 使用requests获取页面信息,用XPath / re 做数据提取 获取每个 ...
- EEPlat的基于浏览器的在线开发技术
EEPlat的开发内容主要包含配置开发和基于API的扩展开发两块内容. EEPlat的配置开发基于后台的配置环境.直接通过界面操作配置就可以. EEPlat的配置平台是用EEPlat自解释构建的.本身 ...
- VisualSVN 5.1.5 破解版 手动破解教程 生成dll文件
VisualSVN 5.1.5 破解版 手动破解教程 生成VisualSVN.Core.L.dll文件 附上本人用到的命令: ildasm "D:\Program Files (x86)\V ...
- OpenCV 常用汇总
cv::Rect矩形类用法 typedef struct CvRect { int x; /* 方形的左上角的x-坐标 */ int y; /* 方形的左上角的y-坐标*/ int width; /* ...
- 2、手把手教React Native实战之从React到RN
###React简介 RN是基于React设计,了解React有助于我们开发RN应用: React希望将功能分解化,让开发变得像搭积木一样,快速而且可维护 React主要有如下3个特点: *作为UI( ...
- Android开发:《Gradle Recipes for Android》阅读笔记(翻译)5.3——使用Robotium进行功能测试
问题: 你想要使用Robotium库测试activity. 解决方案: 增加Robotium依赖,编写自己的测试脚本. 讨论: Android Test Support Library提供类可以操作a ...
- noip2006 金明的预算
题目链接:传送门 题目大意:略.. 题目思路:其实单就这道题来说,一个主件最多两个附件,且附件不再包含附件,所以很简单,但是如果主件的附件无限制,附件也可包含无限制的附件,应该怎么做? 首先推荐一篇论 ...
- pycharm中配置Django运行环境(包括run manage.py task)
1.特别注意Environment variables(环境变量)的配置 DJANGO_SETTINGS_MODULE=(项目名).settings 如: DJANGO_SETTINGS_MODULE ...
- 巨蟒python全栈开发数据库前端7:jQuery框架
每个人的标准不同,看法等等,认识,价值观有所不同,促成了这些矛盾. 1.select例子 <!DOCTYPE html> <html lang="en"> ...
- iOS微信打开App
传统的方式是通过URL Scheme的方式,但是iOS9以后又出了新的更完美的方式Universal Links. 传统的URL Scheme方式微信内置的浏览器都是封锁了所有它投资的公司之外的,只有 ...