Netty(服务端)和DotNetty(客户端)联合使用

2 篇文章 0 订阅

道理咱都懂,但是不会说,废话不多说,直接上代码。

Java

首先引入netty的包

<!-- Netty 引入netty,只需要这一个就足够了-->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.25.Final</version>
</dependency>

服务端代码

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;

/**
 * Netty
 * 服务端
 */
@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<SocketChannel>() {
                        //设置处理请求的逻辑处理类
                        @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;

/**
 * Inbound处理类
 * 给客户端返回一个时间戳
 */
@Configuration
public class ServerInboundGetTimeHandler  extends ChannelInboundHandlerAdapter {
    Logger logger = LoggerFactory.getLogger(ServerInboundGetTimeHandler.class);
    IAction action;
    /**
     * 获取客户端的内容类
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值