C#TCP通讯封装客户端工具类

C#TCP通讯封装客户端工具类

1使用说明

  • 添加接受数据回调函数事件

方式1:通过有参构造函数添加
方式2:调用:public EventHandler<byte[]> AddEventToDataReceived

  • 添加输出日志回调函数事件

方式1:通过有参构造函数添加
方式2:调用:public Action<EMessage, IPEndPoint, int, string> AddEventToOutLog

  • 客户端接受数据线程的数据如何输出日志信息

方式:设置属性【OutputReceivedLog 】
类型:

Null :不输出
Length:仅输出接受数据的长度信息
UTF8:UTF8-解析输出
ASCII:ASCII-解析输出
ByteToString:输出字节的字符串形式

  • 获取当前客户端IP地址和端口号,获取属性【Client】的值;
  • 获取当前客户端连接的服务器的IP地址和端口号,获取属性【Server】的值;
  • 方法

连接服务器:bool ConnectServer(string ip, int port)
关闭客户端:void CloseClient()
连接状态:bool IsConnect { get; private set; }
发送消息:bool Send(byte[] array)

  • 消息类型
    客户端与服务器通讯的消息类型

2封装工具类

using System;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Tcp_Client
{
    public class ClientModel
    {
        private TcpClient _client;

        /// <summary>
        /// 远程终端
        /// </summary>
        private IPEndPoint _remoteEP;

        /// <summary>
        /// 本地终端
        /// </summary>
        private IPEndPoint _localEP;


        /// <summary>
        /// 接受消息回调函数
        /// </summary>
        private EventHandler<byte[]> _callbackEventDataReceived;

        /// <summary>
        /// 日志信息回调函数
        /// int:线程ID
        /// </summary>
        private Action<EMessage, IPEndPoint, int, string> _callbackEventOutLog;

        /// <summary>
        /// 客户端构造函数
        /// </summary>
        /// <param name="callbackEventDataReceived">接受消息回调函数</param>
        /// <param name="callbackEventOutLog">日志信息回调函数;int:线程ID</param>
        public ClientModel(EventHandler<byte[]> callbackEventDataReceived, Action<EMessage, IPEndPoint, int, string> callbackEventOutLog)
        {
            AddEventToDataReceived = callbackEventDataReceived;
            AddEventToOutLog = callbackEventOutLog;
            AddEventToDataReceived = DataReceived;
        }

        public ClientModel()
        {
            AddEventToDataReceived = DataReceived;
        }

        ~ClientModel()
        {
            CloseClient();
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        private void ConnectServer()
        {
            try
            {
                CloseClient();
                // 创建一个 TCP 客户端,连接到服务器的 IP 地址和端口
                _client = new TcpClient();
                _client.Connect(_remoteEP);
                AddLog(EMessage.State, "已连接到服务器。");
                _localEP = (IPEndPoint)_client.Client.LocalEndPoint;
                IsConnect = true;

                // 客户端创建一个新的线程来处理通信
                new Task(HandleClient).Start();
            }
            catch (Exception ex)
            {
                AddLog(EMessage.Exception, $"异常: {ex.Message}");
                CloseClient();
            }
        }

        private void HandleClient()
        {
            try
            {
                NetworkStream stream = _client.GetStream();
                byte[] buffer = new byte[1024];

                while (IsConnect)
                {
                    // 异步读取客户端发送的消息
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0) break;
                    var received = new byte[bytesRead];
                    Array.Copy(buffer, 0, received, 0, bytesRead);
                    _callbackEventDataReceived?.Invoke(null, received);
                }
            }
            catch (Exception ex)
            {
                AddLog(EMessage.Exception, "客户端接受数据线程异常:" + ex.Message);
            }
        }

        private void DataReceived(object sensor, byte[] bytes)
        {
            string message;
            switch (OutputReceivedLog)
            {
                case ETranscoding.Length:
                    message = bytes.Length.ToString();
                    break;
                case ETranscoding.UTF8:
                    message = Encoding.UTF8.GetString(bytes);
                    break;
                case ETranscoding.ASCII:
                    message = Encoding.ASCII.GetString(bytes);
                    break;
                case ETranscoding.ByteToString:
                    var builder = new StringBuilder();
                    builder.Append("[ ");
                    foreach (var b in bytes)
                    {
                        builder.Append(Convert.ToString(b, 16).PadLeft(2, '0').ToUpper() + " ");
                    }
                    builder.Append("]");
                    message = builder.ToString();
                    break;
                default:
                    return;
            }
            AddLog(EMessage.Receive, message);

        }

        private void AddLog(EMessage type, string message)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            _callbackEventOutLog?.Invoke(type, _localEP, threadId, message);
        }

        /********隔离线********隔离线********隔离线********隔离线********隔离线********隔离线********隔离线********/

        /// <summary>
        /// 标识接受缓冲区获取到数据时输出日志信息的方式,默认:不输出
        /// </summary>
        public ETranscoding OutputReceivedLog { get; set; } = ETranscoding.Null;

        public IPEndPoint Server => _remoteEP;
        public IPEndPoint Client => _localEP;

        public EventHandler<byte[]> AddEventToDataReceived
        {
            set
            {
                if (value != null) _callbackEventDataReceived += value;
            }
        }

        public Action<EMessage, IPEndPoint, int, string> AddEventToOutLog
        {
            set
            {
                if (value != null) _callbackEventOutLog += value;
            }
        }

        public bool ConnectServer(string ip, int port)
        {
            _remoteEP = new IPEndPoint(IPAddress.Parse(ip), port);
            ConnectServer();
            return IsConnect;
        }

        public void CloseClient()
        {
            if (IsConnect) _client.Close();
            IsConnect = false;
            try
            {
                if (_client != null)
                {
                    _client.Dispose();
                    _client = null;
                    AddLog(EMessage.State, "断开服务器连接");
                }
            }
            catch (Exception ex)
            {
                AddLog(EMessage.Exception, "断开服务器连接时异常:" + ex.Message);
            }
        }

        public bool IsConnect { get; private set; }

        public bool Send(byte[] array)
        {
            if (_client == null || _client.Connected == false)
            {
                AddLog(EMessage.Send, $"发送失败,请连接服务器!");
                return false;
            }
            // 获取网络流
            NetworkStream stream = _client.GetStream();
            stream.Write(array, 0, array.Length);
            return true;
        }

        public enum EMessage
        {
            [Description("状态信息")]
            State = 1,

            [Description("发送")]
            Send = 3,

            [Description("接受")]
            Receive = 5,

            [Description("异常")]
            Exception = 7,

            [Description("回复")]
            Reply = 9,
        }

        /// <summary>
        /// 接受缓冲区的字节码解析方式
        /// </summary>
        public enum ETranscoding
        {
            /// <summary>
            /// 不输出
            /// </summary>
            Null = 101,

            /// <summary>
            /// 仅输出接受数据的长度信息
            /// </summary>
            Length,

            /// <summary>
            /// UTF8-解析输出
            /// </summary>
            UTF8,

            /// <summary>
            /// ASCII-解析输出
            /// </summary>
            ASCII,

            /// <summary>
            /// 输出字节的字符串形式
            /// </summary>
            ByteToString
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值