DS200:和视觉TCP通讯

TCP通讯接口:

接口:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Sorter.Communication.Socket.Abstractions
{
    public interface ITcpClient : IDisposable
    {
        event EventHandler<bool>? ConnectionChanged;
        event EventHandler<string>? DataReceived;

        bool IsConnected { get; }

        IPEndPoint RemoteEndPoint { get; }

        IPEndPoint IPEndPoint { get; }



        Task<Result> ConnectAsync(string ip, int port, CancellationToken cancellationToken);

        Task<Result> DisconnectAsync();

        Task<Result<string>> ReceiveAsync();

        Task<Result> SendAsync(string data);
    }
}

实现:

cs 复制代码
using Microsoft.Extensions.Logging;
using Sorter.Communication.Socket.Abstractions;
using SuperSocket.Client;
using SuperSocket.ProtoBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Sorter.Communication.Socket.SuperSocket
{
    public class SuperTcpClient : ITcpClient
    {
        private readonly IEasyClient<string> _tcpClient;
        //private readonly ILogger<SuperTcpClient> _logger;


        private bool _disposed;

        private bool _isDisconnectPassively;

        public event EventHandler<bool>? ConnectionChanged;
        public event EventHandler<string>? DataReceived;


        public bool IsConnected { get; private set; }

        public IPEndPoint RemoteEndPoint { get; private set; } = new IPEndPoint(IPAddress.None, 0);

        public IPEndPoint IPEndPoint => (IPEndPoint)_tcpClient.LocalEndPoint;




        public SuperTcpClient(IPipelineFilterFactory<string> pipelineFilterFactory/*, ILogger<SuperTcpClient> logger*/)
        {
            _tcpClient = new EasyClient<string>(pipelineFilterFactory.Create()/*, logger*/);
            //_logger = logger;
        }

        private async void TcpClientClosed(object? sender, EventArgs e)
        {
            if (IsConnected)
            {
                _isDisconnectPassively = true;
            }

            IsConnected = false;
            ConnectionChanged?.Invoke(this, IsConnected);

            if (RemoteEndPoint is not null && !RemoteEndPoint.Address.Equals(IPAddress.None) && !RemoteEndPoint.Port.Equals(0))
            {
                await Task.Run(async () =>
                {
                    while (_isDisconnectPassively && !IsConnected)
                    {
                        try
                        {
                            _tcpClient.PackageHandler -= TcpClientPackageHandler;
                            _tcpClient.Closed -= TcpClientClosed;
                            await _tcpClient.CloseAsync().ConfigureAwait(false);

                            var result = await this.ConnectAsync(RemoteEndPoint.Address.ToString(), RemoteEndPoint.Port, new CancellationTokenSource(2000).Token).ConfigureAwait(false);
                            _isDisconnectPassively = result?.Success is not true;
                        }
                        catch (OperationCanceledException)
                        {

                        }
                        catch (SocketException)
                        {

                        }
                    }
                });
            }
        }

        private ValueTask TcpClientPackageHandler(EasyClient<string> sender, string package)
        {
            DataReceived?.Invoke(this, package);
            //_logger.LogInformation("[{IPEndPoint}] SuperTcpClient Received data: {package}", IPEndPoint, package);
            return ValueTask.CompletedTask;
        }

        ~SuperTcpClient()
        {
            Dispose(false);
        }

        protected virtual async void Dispose(bool disposing)
        {
            if (disposing)
            {
                // 释放托管资源
                _tcpClient.PackageHandler -= TcpClientPackageHandler;
                _tcpClient.Closed -= TcpClientClosed;
            }

            // 释放非托管资源
            try
            {
                await _tcpClient.DisposeAsync();
                _isDisconnectPassively = false;
                IsConnected = false;
                ConnectionChanged?.Invoke(this, IsConnected);
            }
            catch (NullReferenceException)
            {

            }
        }


        public void Dispose()
        {
            if (!_disposed)
            {
                Dispose(true);
            }

            _disposed = true;
            GC.SuppressFinalize(this);
        }



        public async Task<Result> ConnectAsync(string ip, int port, CancellationToken cancellationToken = default)
        {
            try
            {
                if (!IPEndPoint.TryParse($"{ip}:{port}", out var result))
                {
                    return Result<bool>.Fail("IP Format Error");
                }

                _isDisconnectPassively = false;
                _tcpClient.PackageHandler += TcpClientPackageHandler;
                _tcpClient.Closed += TcpClientClosed;
                IsConnected = await _tcpClient.ConnectAsync(result, cancellationToken);
                if (IsConnected)
                {
                    RemoteEndPoint = result;

                    _tcpClient.StartReceive();
                    ConnectionChanged?.Invoke(this, IsConnected);
                }

                return IsConnected ? Result.Ok() : Result.Fail();
            }
            catch (Exception)
            {
                return Result.Fail();
            }
            finally
            {
                if (!IsConnected)
                {
                    _tcpClient.PackageHandler -= TcpClientPackageHandler;
                    _tcpClient.Closed -= TcpClientClosed;
                }
            }
        }

        public async Task<Result> DisconnectAsync()
        {
            _tcpClient.PackageHandler -= TcpClientPackageHandler;
            _tcpClient.Closed -= TcpClientClosed;

            await _tcpClient.CloseAsync();
            _isDisconnectPassively = false;
            IsConnected = false;
            ConnectionChanged?.Invoke(this, IsConnected);
            return Result.Ok();
        }

        public async Task<Result<string>> ReceiveAsync()
        {
            if (!IsConnected)
            {
                return Result<string>.Fail(string.Empty);
            }
            return Result<string>.Ok(await _tcpClient.ReceiveAsync());
        }

        public async Task<Result> SendAsync(string data)
        {
            if (!IsConnected)
            {
                return Result.Fail();
            }

            await _tcpClient.SendAsync(Encoding.UTF8.GetBytes(data));
            //_logger.LogInformation("[{IPEndPoint}] SuperTcpClient Send data: {data}", IPEndPoint, data);
            return Result.Ok();
        }
    }
}

使用的时候:依赖注入使用

cs 复制代码
private readonly ITcpClient _visionClient;

public RecipeService([FromKeyedServices("视觉")] ITcpClient tcpClient)
 {
     _visionClient = tcpClient;

     //当 _visionClient 收到数据时,自动调用 _tcpClient_DataReceived 方法去处理它。
     _visionClient.DataReceived += _tcpClient_DataReceived;
 }

 private void _tcpClient_DataReceived(object? sender, string e)
 {
     if (e.ToUpper().contains("RECIPE"))
     {
         _tcs.SetResult(e);
     }
 }