DotNetty系列二:基本使用
开发环境:VS2017
1.创建二个控制台应用,.net framework4.6.1。一个服务端,一个客户端。
2.nuget,将前五项引入二个控制台应用。
3.服务端代码:注释写代码里了
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Server
{class Program{static void Main(string[] args) => RunServerAsync().Wait();static async Task RunServerAsync(){// 主工作线程组,设置为1个线程var bossGroup = new MultithreadEventLoopGroup(1);// 工作线程组,默认为内核数*2的线程数var workerGroup = new MultithreadEventLoopGroup();try{//声明一个服务端Bootstrap,每个Netty服务端程序,都由ServerBootstrap控制,//通过链式的方式组装需要的参数var bootstrap = new ServerBootstrap();bootstrap.Group(bossGroup, workerGroup) // 设置主和工作线程组.Channel<TcpServerSocketChannel>() // 设置通道模式为TcpSocket.Option(ChannelOption.SoBacklog, 100) // 设置网络IO参数等,这里可以设置很多参数,当然你对网络调优和参数设置非常了解的话,你可以设置,或者就用默认参数吧.Option(ChannelOption.SoKeepalive, true)//保持连接.ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>{ //工作线程连接器 是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输//同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理IChannelPipeline pipeline = channel.Pipeline;//业务handler ,这里是实际处理业务的Handlerpipeline.AddLast(new HelloServerHandler());}));// bootstrap绑定到指定端口的行为 就是服务端启动服务,同样的Serverbootstrap可以bind到多个端口IChannel boundChannel = await bootstrap.BindAsync(3399);Console.WriteLine("服务启动");Console.ReadLine();//关闭服务await boundChannel.CloseAsync();}finally{//释放工作组线程await Task.WhenAll(bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)),workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)));}}}public class HelloServerHandler : ChannelHandlerAdapter //管道处理基类,较常用{public override bool IsSharable => true;//标注一个channel handler可以被多个channel安全地共享。// 重写基类的方法,当消息到达时触发,这里收到消息后,在控制台输出收到的内容,并原样返回了客户端public override void ChannelRead(IChannelHandlerContext context, object message){if (message is IByteBuffer buffer){Console.WriteLine("从客户端接收: " + buffer.ToString(Encoding.UTF8));}//编码成IByteBuffer,发送至客户端string msg = "服务端从客户端接收到内容后返回,我是服务端";byte[] messageBytes = Encoding.UTF8.GetBytes(msg);IByteBuffer initialMessage = Unpooled.Buffer(messageBytes.Length);initialMessage.WriteBytes(messageBytes);context.WriteAsync(initialMessage);//写入输出流}// 输出到客户端,也可以在上面的方法中直接调用WriteAndFlushAsync方法直接输出public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();//捕获 异常,并输出到控制台后断开链接,提示:客户端意外断开链接,也会触发public override void ExceptionCaught(IChannelHandlerContext context, Exception exception){Console.WriteLine("异常: " + exception);context.CloseAsync();}//客户端连接进来时public override void HandlerAdded(IChannelHandlerContext context){Console.WriteLine($"客户端{context}上线.");base.HandlerAdded(context);}//客户端下线断线时public override void HandlerRemoved(IChannelHandlerContext context){Console.WriteLine($"客户端{context}下线.");base.HandlerRemoved(context);}//服务器监听到客户端活动时public override void ChannelActive(IChannelHandlerContext context){Console.WriteLine($"客户端{context.Channel.RemoteAddress}在线.");base.ChannelActive(context);}//服务器监听到客户端不活动时public override void ChannelInactive(IChannelHandlerContext context){Console.WriteLine($"客户端{context.Channel.RemoteAddress}离线了.");base.ChannelInactive(context);}}
}
4.客户端代码:和服务端基本上差不多
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;namespace Client
{class Program{static void Main(string[] args) => RunClientAsync().Wait();static async Task RunClientAsync(){var group = new MultithreadEventLoopGroup();try{var bootstrap = new Bootstrap();bootstrap.Group(group).Channel<TcpSocketChannel>().Option(ChannelOption.TcpNodelay, true).Handler(new ActionChannelInitializer<ISocketChannel>(c =>{IChannelPipeline pipeline = c.Pipeline;pipeline.AddLast(new HelloClientHandler());}));IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3399));Console.ReadLine();await clientChannel.CloseAsync();}finally{await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1));}}}class HelloClientHandler : ChannelHandlerAdapter{public override void ChannelActive(IChannelHandlerContext context){Console.WriteLine("我是客户端.");Console.WriteLine($"连接至服务端{context}.");//编码成IByteBuffer,发送至服务端string message = "客户端1";byte[] messageBytes = Encoding.UTF8.GetBytes(message);IByteBuffer initialMessage = Unpooled.Buffer(messageBytes.Length);initialMessage.WriteBytes(messageBytes);context.WriteAndFlushAsync(initialMessage);}public override void ChannelRead(IChannelHandlerContext context, object message){if (message is IByteBuffer buffer){Console.WriteLine($"IByteBuffer方式,从服务端接收:{buffer.ToString(Encoding.UTF8)}");}}public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();public override void HandlerAdded(IChannelHandlerContext context){Console.WriteLine($"服务端{context}上线.");base.HandlerAdded(context);}public override void HandlerRemoved(IChannelHandlerContext context){Console.WriteLine($"服务端{context}下线.");base.HandlerRemoved(context);}}
}
5.运行效果:
项目下载地址:项目下载
DotNetty系列二:基本使用相关推荐
- 搜索引擎ElasticSearchV5.4.2系列二之ElasticSearchV5.4.2+kibanaV5.4.2+x-packV5.4.2安装
相关博文: 搜索引擎ElasticSearchV5.4.2系列一之ES介绍 搜索引擎ElasticSearchV5.4.2系列二之ElasticSearchV5.4.2+klanaV5.4.2+x-p ...
- 【C++自我精讲】基础系列二 const
[C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...
- 人工智能算法通俗讲解系列(二):逻辑回归
2019独角兽企业重金招聘Python工程师标准>>> 今天,我们介绍的机器学习算法叫逻辑回归.它英语名称是Logistic Regression,简称LR. 跟之前一样,介绍这个算 ...
- 【算法系列 二】Stack
为什么80%的码农都做不了架构师?>>> 栈应用的场景: 1.括号问题 2.后缀表达式 3.深度优先遍历 4.保存现场 1. 给定字符串,仅由"()[]{}" ...
- 《CDN 之我见》系列二:原理篇(缓存、安全)
2019独角兽企业重金招聘Python工程师标准>>> <CDN之我见>共由三个篇章组成,分为原理篇.详解篇和陨坑篇.本篇章适合那些从未接触过.或仅了解一些 CDN 专业 ...
- SEO系列二:何为用户体验?如何做好用户体验?
昨天写了一篇<SEO系列一:SEO是什么?SEO有什么意义?>的文章,受到了汇道童鞋们的支持和鼓舞,周珍在这里和大家说声谢谢.甚至还有童鞋说期待我写到SEO系列2000,是否能写到2000 ...
- 一步步构建多层架构系列二之设计模式运用篇
上节我们讲到数据对象创建的管理,那么如何管理数据访问类的对象创建呢?先从为什么需要设计模式的原理说起吧 为了更好的理解设计思想,我尽可能的用实例来演示推进.但随着需求的增加,程序将越来越复杂.此时就有 ...
- 机器学习入门系列二(关键词:多变量(非)线性回归,批处理,特征缩放,正规方程
机器学习入门系列二(关键词:多变量(非)线性回归,批处理,特征缩放,正规方程) 目录(?)[+] 一多变量的线性回归 二批处理 三特征缩放 四正规方程 五多变量非线性回归 一.多变量的线性回归 在#机 ...
- 图层几何学 -- iOS Core Animation 系列二
<图层树和寄宿图 -- iOS Core Animation 系列一>介绍了图层的基础知识和一些属性方法.这篇主要内容是学习下图层在父图层上怎么控制位置和尺寸的. 1.布局 首先看一张例图 ...
最新文章
- 干货!解读2016-2017全球人工智能技术及产业发展的现状及趋势~
- “AV终结者/8749”病毒清理办法
- ssh架构之hibernate(一)简单使用hibernate完成CRUD
- 三招看穿ERP软件是否可行
- html邮件和纯文本邮件区别,邮件营销必读系列五--纯文本和HTML邮件类型——哪一种邮件类型更适合你?...
- comsol显示电场计算结果_在 COMSOL 中构建磁流体动力学多物理场模型
- 硬核!有人开源了一套呼吸机方案!
- hive 导出json格式 文件_Magicodes.IE在.NET Core中通过请求头导出多种格式文件
- javaweb学习总结—jsp简单标签标签库开发
- 基于CUDA的VTI介质有限差分正演模拟与逆时偏移及ADCIGs提取
- 中国物流领域首次!菜鸟路径规划算法入围全球最高工业奖项
- KandQ:单例模式的七种写法及其相关问题解析
- GitHub上最流行的10000个Java都使用了哪些库?
- 多个表结果的并列显示
- 解决xftp6 要继续使用此程序您必须应用最新的更新或使用新版本
- 《web安全原理分析与实践》
- 服务器虚拟内存可以设置其他盘,Win7系统如何把虚拟内存设置在其它盘符?
- 微缩脚步趋缓 摩尔定律由于EUV微影技术延迟失去动力
- 太湖2018年渔业产值达7.3亿元 今年大闸蟹产量将降低
- 数据链路层协议 ——— 以太网协议