首页 > 其他分享 >DotNetty 封装的 UdpClient

DotNetty 封装的 UdpClient

时间:2024-02-04 15:35:30浏览次数:20  
标签:null return UdpClient NettyDataReceiveHandle 封装 new DotNetty ResponseCompletionS

DotNetty 资料较少,UdpClient 和 TcpClient 略有不同

public class UdpCommunicator : ICommunicator
{
    private IChannel? _ClientChannel;
    private Bootstrap? _Bootstrap;
    IEventLoopGroup? _LoopGroup;
    private TaskCompletionSource<byte[]> _ResponseCompletionSource;
    CancellationTokenSource _TokenSource;
    NettyDataReceiveHandle _NettyDataReceiveHandle = new NettyDataReceiveHandle();
    public IPEndPoint? LocalEndPoint { get; private set; }
    public IPEndPoint? RemoteEndPoint { get; private set; }

    public bool IsConnected { get; private set; }

    public event Action<byte[]> OnDataReceive;
    internal UdpCommunicator()
    {
        LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);
        InitNetty();
    }
    /// <summary>
    /// 用于绑定的本地端点
    /// </summary>
    /// <param name="iPEndPoint"></param>
    internal UdpCommunicator(IPEndPoint iPEndPoint)
    {
        LocalEndPoint = iPEndPoint;
        InitNetty();
    }
    void InitNetty()
    {
        _NettyDataReceiveHandle.OnBytesReceived += receiveBytes => Task.Run(() =>
        {
            OnDataReceive?.Invoke(receiveBytes);
            _ResponseCompletionSource?.TrySetResult(receiveBytes);
        });
        _NettyDataReceiveHandle.OnDisconnected += () => IsConnected = false;

        _LoopGroup = new MultithreadEventLoopGroup();
        
    }

    public bool Connect(IPEndPoint remoteEndPoint)
    {
        try
        {

            RemoteEndPoint = remoteEndPoint;

            _Bootstrap = new Bootstrap();
            _Bootstrap
                .Group(_LoopGroup)
                .Channel<SocketDatagramChannel>()
                .Option(ChannelOption.SoBroadcast, true)
                .Handler(new ActionChannelInitializer<IChannel>(channel =>
                {
                    IChannelPipeline pipeline = channel.Pipeline;
                    pipeline.AddLast(_NettyDataReceiveHandle);
                }));

            _ClientChannel = _Bootstrap.BindAsync(LocalEndPoint).Result;
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }

    }

    public bool DisConnect()
    {
        _ClientChannel?.CloseAsync().Wait();
        _ClientChannel = null;
        return true;
    }

    public void Dispose()
    {
        DisConnect();
        _LoopGroup?.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)).Wait();
        _LoopGroup = null;
    }
    object sendLock = new object();
    public byte[]? Send(byte[]? content)
    {
        lock (sendLock)
        {
            _ResponseCompletionSource = new TaskCompletionSource<byte[]>();
            using (_TokenSource = new CancellationTokenSource(600))
            {
                _TokenSource.Token.Register(() => _ResponseCompletionSource.TrySetCanceled(), useSynchronizationContext: false);
                bool sendResult = SendAsync(content).Result;
                if(!sendResult) return null;
                try
                {
                    return _ResponseCompletionSource.Task.Result;
                }
                catch (TaskCanceledException)
                {
                    _ResponseCompletionSource = null;
                    return null;
                }
                catch (AggregateException)
                {
                    _ResponseCompletionSource = null;
                    return null;
                }
            }
        }
    }

    public async Task<bool> SendAsync(byte[]? content)
    {
        if(_ClientChannel is null) return false;
        IByteBuffer byteBuffer = Unpooled.WrappedBuffer(content);
        await _ClientChannel.WriteAndFlushAsync(new DatagramPacket(byteBuffer, RemoteEndPoint));
        return true;
    }
}
class NettyDataReceiveHandle : SimpleChannelInboundHandler<DatagramPacket>
{
    public override bool IsSharable => true;
    public event Func<byte[], Task>? OnBytesReceived;
    public event Action? OnDisconnected;
    protected override void ChannelRead0(IChannelHandlerContext ctx, DatagramPacket packet)
    {
        var byteBuffer = packet.Content;
        byte[] bytes = new byte[byteBuffer.ReadableBytes];
        byteBuffer.GetBytes(byteBuffer.ReaderIndex, bytes);
        OnBytesReceived?.Invoke(bytes);
    }
    public override void ChannelReadComplete(IChannelHandlerContext ctx)
    {
        ctx.Flush();
    }

    public override void ExceptionCaught(IChannelHandlerContext ctx, Exception e)
    {
        ctx.CloseAsync();
        OnDisconnected?.Invoke();
    }
}

 

标签:null,return,UdpClient,NettyDataReceiveHandle,封装,new,DotNetty,ResponseCompletionS
From: https://www.cnblogs.com/cchong005/p/18006325

相关文章

  • 用VB6.0封装DLL组件并在EXCEL中调用
    使用程序:1、MicrosoftOfficeExcel20032、MicrosoftVisualBasic6.0 案例:在工作表的C1单元格得出A1单元格+B1单元格的值。设计的VBA代码:SubTest()  OnErrorResumeNext  Range("C1")=Cells(1,1)+Cells(1,2)EndSub  第一部分、使用VB6.0制作DL......
  • JDBC的简单封装
    1、dataSource.propertiesdriver=oracle.jdbc.driver.OracleDriverurl=jdbc:oracle:thin:@localhost:1521:orclusername=usernamepassword=password2、代码示例packagecom.example;importjava.io.IOException;importjava.io.InputStream;importjava.sql.Connection;imp......
  • uniapp sqlite方法封装
    vardbName='xxx'//数据库名称vardbPath='_doc/xxx.db'//数据库地址,推荐以下划线为开头_doc/xxx.db//判断数据库是否打开constisOpen=(plus:any)=>{//数据库打开了就返回true,否则返回falsevaropen=plus.sqlite.isOpenDatabase({name:......
  • Vue中如何对Axios进行二次封装
    作为一个前端开发者,你一定对Axios这个强大的HTTP库非常熟悉。它不仅简化了与后端API的通信,而且还提供了许多强大的功能,如拦截器、取消请求等。但是在实际开发中,我们经常需要对Axios进行二次封装,以便更好地适应我们的业务需求。今天,我将为大家分享一下如何在Vue中对Axios进行二次封......
  • vue3,封装检测元素大小变化的自定义指令
    1//resizeObserver.ts2//监听元素大小变化的指令3constmap=newWeakMap()4constob=newResizeObserver((entries)=>{5for(constentryofentries){6//获取dom元素的回调7consthandler=map.get(entry.target)8//存在回调函......
  • wpf 数据绑定 INotifyPropertyChanged封装
    BindableBase.cspublicabstractclassBindableBase:INotifyPropertyChanged{publiceventPropertyChangedEventHandlerPropertyChanged;//调用方法:publicstringName{get=>name;set{SetProperty<string>(refname,value);}}......
  • D20XB100-ASEMI整流桥D20XB100参数、封装、规格
    编辑:llD20XB100-ASEMI整流桥D20XB100参数、封装、规格型号:D20XB100品牌:ASEMI正向电流(Id):20A反向耐压(VRRM):1000V正向浪涌电流:300A正向电压(VF):1.05V引脚数量:5芯片个数:4芯片尺寸:MIL功率(Pd):大功率设备封装:GBJ-5工作温度:-40°C~150°C类型:插件、整流桥D20XB100描述:ASEMI品牌D20XB100是采......
  • D20XB100-ASEMI整流桥D20XB100参数、封装、规格
    编辑:llD20XB100-ASEMI整流桥D20XB100参数、封装、规格型号:D20XB100品牌:ASEMI正向电流(Id):20A反向耐压(VRRM):1000V正向浪涌电流:300A正向电压(VF):1.05V引脚数量:5芯片个数:4芯片尺寸:MIL功率(Pd):大功率设备封装:GBJ-5工作温度:-40°C~150°C类型:插件、整流桥D20XB100描述:ASEMI......
  • D20XB60-ASEMI整流桥D20XB60参数、封装、尺寸
    编辑:llD20XB60-ASEMI整流桥D20XB60参数、封装、尺寸型号:D20XB60品牌:ASEMI封装:GBJ-5最大重复峰值反向电压:600V最大正向平均整流电流(Vdss):20A功率(Pd):芯片个数:4引脚数量:5类型:插件、整流桥正向浪涌电流:300A正向电压:1.05V最大输出电压(RMS):封装尺寸:如图工作温度:-40°C~1......
  • 封装
    ......