TCPClient.cs 7.8 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Dolen.Communication.TCP
{
    public class TCPClient
    {
        Thread threadRecv = null; // 负责接收消息的线程;
        Socket clientSocket = null;
        int buffLength = 1024;// 定义一个1M的缓存区;
        log4net.ILog Log;
        private bool loop = false;
        /// <summary>
        /// 消息变化委托
        /// </summary>
        /// <param name="msg">服务端发送的消息</param>
        public delegate void MsgEventHandler(string msg);

        public delegate void ConnectedStateEventHandler(bool state);
        /// <summary>
        /// 消息事件
        /// </summary>
        public event MsgEventHandler MsgEvent;
        public event ConnectedStateEventHandler ConnectedStateEvent;
        /// <summary>
        /// 是否打开调试
        /// </summary>
        public bool IsDebug { get; set; } = false;
        /// <summary>
        /// 服务端信息
        /// </summary>
        public string ServerInfo { get
            {
                return string.Format("{0}:{1}",ip,port.ToString());
            } }
        /// <summary>
        /// 服务端IP
        /// </summary>
        private string ip;
        /// <summary>
        /// 服务端端口
        /// </summary>
        private int port;
        private bool connectState = false;
        /// <summary>
        /// 连接状态
        /// </summary>
        public bool Connected { get { if (clientSocket == null) return false; else return connectState && clientSocket.Connected; } }
        public TCPClient(string ip = "127.0.0.1", int port = 8888, string logName = "TCPClient")
        {
            Log = log4net.LogManager.GetLogger(logName);
            this.ip = ip;
            this.port = port;
        }
        /// <summary>
        /// 开启服务
        /// </summary>
        public void Connect()
        {
            loop = true;
            IPAddress address = IPAddress.Parse(ip);
            // 创建包含ip和端口号的网络节点对象;
            IPEndPoint endPoint = new IPEndPoint(address, port);
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(endPoint);
                threadRecv = new Thread(RecMsg);
                threadRecv.Start(clientSocket);
                connectState = true;
                Log.Info(string.Format("客户端[{0}]连接服务端[{1}]成功", clientSocket.RemoteEndPoint.ToString(), ServerInfo));
            }
            catch(Exception ex)
            {
                connectState = false;
                Log.Error(string.Format("客户端[{0}]连接服务端[{1}]失败", clientSocket.RemoteEndPoint.ToString(), ServerInfo),ex);
            }
            ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);

        }
        public void DisConnect()
        {
            if(clientSocket.Connected)
            {
                loop = false;
                try
                {
                    string client = clientSocket.RemoteEndPoint.ToString();
                    connectState = false;
                    threadRecv.Abort();
                    threadRecv = null;
                    clientSocket.Close();
                    Log.Info(string.Format("客户端[{0}]断开服务端[{1}]成功", client, ServerInfo));
                }
                catch(Exception e)
                {
                    Log.Error(string.Format("客户端[{0}]断开服务端[{1}]成功", clientSocket.RemoteEndPoint.ToString(), ServerInfo),e);
                }

                ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);
            }
        }

        void RecMsg(object sokConnectionparn)
        {
            Socket sokClient = sokConnectionparn as Socket;           
            while (loop)
            {
                // 定义一个缓存区;
                byte[] arrMsgRec = new byte[buffLength];
                // 将接收到的数据存入到输入  arrMsgRec中;
                int length = -1;
                if (sokClient.Poll(-1, SelectMode.SelectRead))
                {
                    try
                    {
                        length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
                        if (length == 0)//连接正常断开
                        {
                            connectState = false;
                            Log.Info(string.Format("服务端[{1}]断开与客户端[{0}]的连接", clientSocket.RemoteEndPoint.ToString(), ServerInfo));
                            ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);
                            break;
                        }
                    }
                    catch (SocketException se)
                    {
                        connectState = false;
                        Log.Error(string.Format("客户端[{0}]接收服务端[{1}]的消息出现异常", clientSocket.RemoteEndPoint.ToString(), ServerInfo), se);
                        ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);
                        break;
                    }
                    catch (Exception e)
                    {
                        connectState = false;
                        Log.Error(string.Format("客户端[{0}]接收服务端[{1}]的消息出现异常", clientSocket.RemoteEndPoint.ToString(), ServerInfo), e);
                        ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);
                        break;
                    }
                }

                if (length > 0)
                {
                    string strMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);// 将接收到的字节数据转化成字符串;
                    if (IsDebug)
                        Log.Debug(string.Format("客户端[{0}]收到服务端[{1}]的消息:{2}[{3}]", clientSocket.RemoteEndPoint.ToString(), ServerInfo, strMsg, string.Join(" ", arrMsgRec)));
                    Log.Info(string.Format("客户端[{0}]收到服务端[{1}]的消息:{2}", clientSocket.RemoteEndPoint.ToString(), ServerInfo, strMsg));
                    MsgEvent?.Invoke(strMsg);
                }

            }
        }

        /// <summary>
        /// 向客户端发送信息
        /// </summary>
        public void SendMsg(string txt)
        {
            try
            {
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(txt); // 将要发送的字符串转换成Utf-8字节数组;
                                                                         // arrSendMsg[0] = 0; // 表示发送的是消息数据
                                                                         //Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length);    
                if (Connected)
                {    
                    int len = clientSocket.Send(arrMsg);
                    Log.Info(string.Format("客户端[{0}]向服务端[{1}]发送消息:{2}[{3} Bytes]", clientSocket.RemoteEndPoint.ToString(), ServerInfo, txt, len));
                }
                else
                {
                    Log.Info(string.Format("客户端[{0}]向服务端[{1}]发送消息失败,网络已断开:{2}", clientSocket.RemoteEndPoint.ToString(), ServerInfo, txt));
                }
            }
            catch (Exception e)
            {
                connectState = false;
                Log.Error(string.Format("客户端[{0}]向服务端[{1}]发送消息异常:{2}", clientSocket.RemoteEndPoint.ToString(), ServerInfo, txt), e);
                ConnectedStateEvent?.Invoke(connectState && clientSocket.Connected);
            }

        }
    }

}