道理咱都懂,但是不会说,废话不多说,直接上代码。
Java
首先引入netty的包
io.netty netty-all4.1.25.Final
服务端代码
package com.ruoyi.common.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; @Component @Configuration public class NettyServer { //handle已经添加 public void startServer() { System.out.println("服务端启动成功"); //创建两个线程组,用于接收客户端的请求任务,创建两个线程组是因为netty采用的是反应器设计模式 //反应器设计模式中bossGroup线程组用于接收 EventLoopGroup bossGroup = new NioEventLoopGroup(); //workerGroup线程组用于处理任务 EventLoopGroup workerGroup = new NioEventLoopGroup(); //创建netty的启动类 ServerBootstrap bootstrap = new ServerBootstrap(); //创建一个通道 ChannelFuture f = null; try { bootstrap.group(bossGroup, workerGroup) //设置线程组 .channel(NioServerSocketChannel.class) //设置通道为非阻塞IO .option(ChannelOption.SO_BACKLOG, 128) //设置日志 .option(ChannelOption.SO_RCVBUF, 32 * 1024) //接收缓存 .childOption(ChannelOption.SO_KEEPALIVE, true)//是否保持连接 .localAddress(new InetSocketAddress(61005)) .childHandler(new ChannelInitializer() { //设置处理请求的逻辑处理类 @Override protected void initChannel(SocketChannel ch) throws Exception { //ChannelPipeline是handler的任务组,里面有多个handler ChannelPipeline pipeline = ch.pipeline(); LoggerFactory.getLogger(NettyServer.class).debug("新的链接进入..."); //心跳设置 pipeline.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS)); pipeline.addLast("logging",new LoggingHandler(LogLevel.DEBUG)); pipeline.addLast("handler",new ServerInboundGetTimeHandler()); } }); f = bootstrap.bind(61005).sync();//阻塞端口号,以及同步策略 f.channel().closeFuture().sync();//关闭通道 } catch (InterruptedException e) { e.printStackTrace(); } finally { //优雅退出 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
现在已经服务器开启了,下面开始设置handle处理类
package com.ruoyi.common.netty; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONPatch; import com.ruoyi.common.action.IAction; import com.ruoyi.common.action.impl.LoginAction; import com.ruoyi.common.action.impl.VersionAction; import com.ruoyi.common.core.constant.NettyConstant; import com.ruoyi.common.security.auth.AuthUtil; import com.ruoyi.system.api.model.LoginUser; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import java.text.SimpleDateFormat; import java.util.Date; @Configuration public class ServerInboundGetTimeHandler extends ChannelInboundHandlerAdapter { Logger logger = LoggerFactory.getLogger(ServerInboundGetTimeHandler.class); IAction action; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //将传递过来的内容转换为ByteBuf对象 ByteBuf buf = (ByteBuf) msg; //和文件IO一样,用一个字节数组读数据 byte[] reg = new byte[buf.readableBytes()]; buf.readBytes(reg); //将读取的数据转换为字符串 String body = new String(reg, "UTF-8"); try{ 处理body }catch (Exception e){ logger.error("发送的消息错误"); ctx.close(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { NettyMap.remove(ctx); ctx.close(); logger.error("链接异常断开"); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { //如果超时没有收到心跳会进入这里 if (evt instanceof IdleStateEvent) {//超时事件 IdleStateEvent idleEvent = (IdleStateEvent) evt; if (idleEvent.state() == IdleState.READER_IDLE) {//读 NettyMap.remove(ctx); ctx.close(); } } super.userEventTriggered(ctx, evt); } }
服务器代码已经写完了,下面开始客户端代码。
C#客户端代码
首先引入两个dll
1、DotNetty.dll
2、DotNetty.Extensions.dll
using BoardNetty.com.ruoyi.board; using BoardNetty.com.ruoyi.entity; using BoardNetty.com.ruoyi.response; using DotNetty.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace BoardNetty { public class NettyClient { private static NettyClient nettyClient = null; private string serverIp; private int port; TcpSocketClient client = null; Thread thread = null; public static NettyClient GetNettyClient() { if (nettyClient == null) { nettyClient = new NettyClient(); } return nettyClient; } #region 初始化服务器链接 public void init() { this.serverIp = "127.0.0.1"; this.port = 61005; } public void init(string serverIp) { this.serverIp = serverIp; this.port = 61005; } public void init(int port) { this.serverIp = "127.0.0.1"; this.port = port; } public void init(string serverIp, int port) { this.serverIp = serverIp; this.port = 61005; } #endregion public void connection() { client = new TcpSocketClient(serverIp, port); toevent(); } public void heart() { try { thread = new Thread(() => { while (true) { Thread.Sleep(5000); var bytes = Encoding.UTF8.GetBytes("我是心跳"); if (client != null) { client.SendAsync(bytes); } } }); thread.IsBackground = true; thread.Start(); } catch (Exception) { throw; } } private void toevent() { client.onPipeline(pipeLine => { }); client.onConnect(() => { //链接成功之后默认进行登录 var bytes = Encoding.UTF8.GetBytes("hello i am C#"); client.SendAsync(bytes); heart(); }); client.onReceive(bytes => { string msg = System.Text.UTF8Encoding.UTF8.GetString(bytes); //处理逻辑(msg) }); client.onException(ex => { Console.WriteLine("OnException:" + ex); }); client.onClose(ex => { Console.WriteLine("OnClose:" + ex); //restart //client.ConnectAsync(); }); client.ConnectAsyncs(); } } }
好了现在就可以用了。
最后把dll放在下面
DotNetty.zip-C#文档类资源-CSDN下载DotNetty.zip更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/sdf295953/54191709
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)