TcpServer.cs 12.3 KB
using OnlineStore;
using DL.Utils;
using log4net;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DL.Com.TCP
{
    public class TcpServer
    {
        /// <summary>
        /// 接受消息时的间隔
        /// </summary>
        public static int ReviceMsgMS = 10;

        private Thread m_serverThread;
        private Socket m_serverSocket;
        public delegate void ReviceMsgEventHandler(TcpClientBean client, string Msg,byte[] data);
        public delegate void ClientOffLineEventHandler(TcpClientBean client);
        public delegate void AcceptClientEventHandler(TcpClientBean client);

        public event ReviceMsgEventHandler ReviceMsgEvent;
        public event AcceptClientEventHandler AcceptClientEvent;
        public event ClientOffLineEventHandler ClientOfflineEvent;
        private bool isRun = false;
        private int serverPort = 0;
        public TcpServer(int m_serverPort)
        {
            this.serverPort = m_serverPort;
        }
        private void logLocalIp()
        {
            string[] addresses = GetLocalAddresses();
            string iplist = crc.GetString("Res0041","本机IP")+":[";
            if (addresses.Length > 0)
            {
                for (int i = 0; i < addresses.Length; i++)
                {
                    if (addresses.Length != 0)
                    {
                        iplist = iplist + " " + addresses[i];
                    }
                }
            }
            LogUtil.Info(iplist + "]");
        }
        public bool Connected { get { return m_serverSocket != null && m_serverSocket.Connected; } }
        /// <summary>
        /// 开始服务
        /// </summary>
        public bool Start()
        {
            try
            {
                isRun = true;
                m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, serverPort);
                m_serverSocket.Bind(localEndPoint);
                m_serverSocket.Listen(10);

                m_serverThread = new Thread(new ThreadStart(ReceiveAccept));
                m_serverThread.Start();

                LogUtil.Info(" Server start listen : " + serverPort);
                logLocalIp();
                return true;
                //this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Server started.");
            }
            catch (SocketException se)
            {
                LogUtil.Error("Tcpserver Start 报错",se);
            }
            catch (Exception ex)
            {
                LogUtil.Error("Tcpserver Start 报错", ex);
            }
            return false;
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public bool Stop()
        {
            try
            {
                isRun = false;
                m_serverThread.Interrupt(); // 线程终止
                m_serverSocket.Close(); // Socket Close  
                return true;
            }
            catch (Exception ex)
            {
                LogUtil.Error("Tcpserver Stop报错", ex);
            }
            return false;
        }

        private void ReceiveAccept()
        {
            while (isRun)
            {
                TcpClientBean client = new TcpClientBean();
                try
                {
                    client.ClientSocket = m_serverSocket.Accept();
                    IPEndPoint clientipe = (IPEndPoint)client.ClientSocket.RemoteEndPoint;
                    client.IP = clientipe.Address.ToString();
                    client.Port = clientipe.Port;
                    LogUtil.Info("[" + serverPort + "]有新的客户端连接上:[" + client.AddStr + "]");
                    AcceptClientEvent?.Invoke(client);
                    Task.Factory.StartNew(delegate { ReceiveMessages(client); });

                }
                catch (Exception ex)
                {
                    LogUtil.Error("ReceiveAccept方法,客户端【" + client.AddStr + "】", ex);
                    //throw new Exception(ex.Message);
                }
            }
        }
        //   private StringBuilder sb = new StringBuilder();             //这个是用来保存:接收到了的,但是还没有结束的消息
        private int receiveBufferSize = 1024;
        public string terminateString = "\r\n";
        public void ReceiveMessages(TcpClientBean client)            //这个函数会被以线程方式运行
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                Socket socket = (Socket)client.ClientSocket;
                while (true)
                {
                    byte[] buffer = new byte[receiveBufferSize];  //buffer大小,此处为1024
                    if(socket.Poll(0,SelectMode.SelectRead))
                    {
                        int receivedSize = socket.Receive(buffer);
                        if (receivedSize > 0)
                        {
                            string rawMsg = Encoding.ASCII.GetString(buffer, 0, receivedSize);
                            byte[] data = new byte[receivedSize];
                            Array.Copy(buffer, 0, data, 0, receivedSize);
                            int rnFixLength = terminateString.Length;   //这个是指消息结束符的长度,此处为\r\n
                            if (rnFixLength == 0)//无结束符
                            {
                                this.ReviceMsgEvent?.Invoke(client, rawMsg, data);//无消息结束符,直接触发消息接收完成事件
                            }
                            else
                            {
                                for (int i = 0; i < rawMsg.Length;)               //遍历接收到的整个buffer文本
                                {
                                    if (i <= rawMsg.Length - rnFixLength)
                                    {
                                        if (rawMsg.Substring(i, rnFixLength) != terminateString)//非消息结束符,则加入sb
                                        {
                                            sb.Append(rawMsg[i]);
                                            i++;
                                        }
                                        else
                                        {
                                            this.ReviceMsgEvent?.Invoke(client, sb.ToString(), data);//找到了消息结束符,触发消息接收完成事件
                                            sb = new StringBuilder();
                                            i += rnFixLength;
                                        }
                                    }
                                    else
                                    {
                                        sb.Append(rawMsg[i]);
                                        i++;
                                    }
                                }
                            }
                        }
                        else
                        {
                            ClientOfflineEvent?.Invoke(client);
                            LogUtil.Info($"客户端【{client.AddStr}】已断开");
                            break;
                        }
                    }

                    Thread.Sleep(ReviceMsgMS);
                }
            }
            catch (SocketException e)
            {
                LogUtil.Error($"客户端【{client.AddStr}】:{e.StackTrace}", e);
                ClientOfflineEvent?.Invoke(client);
            }
            catch (Exception ex)
            {
                LogUtil.Error($"客户端【{client.AddStr}】:{ex.StackTrace}", ex);
                ClientOfflineEvent?.Invoke(client);
            }
        }
        //private void ReceiveMessages(Client client)
        //{
        //    try
        //    {
        //        while (true)
        //        {
        //            byte[] receiveBuffer = new byte[1024];

        //            //int size = ;
        //            int size = client.ClientSocket.Receive(receiveBuffer);

        //            string strReceiveData = Encoding.ASCII.GetString(receiveBuffer, 0, size);

        //            if (!string.IsNullOrEmpty(strReceiveData))
        //            {
        //                Log.info(LOGGER, "收到数据:" + strReceiveData);
        //                // this.AddRunningInfo(">> Receive data from [" + client.ClientSocket.RemoteEndPoint.ToString()+ "]:" + strReceiveData);
        //                string strSendData = "OK. The content is:" + strReceiveData;
        //                //Log.info(LOGGER, "OK. The content is:" + strReceiveData);
        //                int sendBufferSize = Encoding.Unicode.GetByteCount(strSendData);
        //                byte[] sendBuffer = new byte[sendBufferSize];
        //                sendBuffer = Encoding.Unicode.GetBytes(strSendData);

        //                client.ClientSocket.Send(sendBuffer);
        //            }
        //        }
        //    }
        //    catch (SocketException e)
        //    {
        //        Log.error(LOGGER, e.ToString());
        //    }
        //    catch (Exception ex)
        //    {
        //        LOGGER.Error(ex.ToString());
        //    }
        //}
        /// <summary>
        /// 获取本机地址列表
        /// </summary>
        public static string[] GetLocalAddresses()
        {
            // 获取主机名
            string strHostName = Dns.GetHostName();

            // 根据主机名进行查找
            IPHostEntry iphostentry = Dns.GetHostEntry(strHostName);

            List<string> retval = new List<string>();
            foreach (IPAddress ipaddress in iphostentry.AddressList)
            {
                if (ipaddress.AddressFamily != AddressFamily.InterNetworkV6)
                {
                    retval.Add(ipaddress.ToString());
                }
            }
            return retval.ToArray();
        }
        /// <summary>
        /// 端口是否被占用
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        public static bool PortInUse(int port)
        {
            bool result = false;
            IPGlobalProperties iPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] activeTcpListeners = iPGlobalProperties.GetActiveTcpListeners();
            IPEndPoint[] array = activeTcpListeners;
            for (int i = 0; i < array.Length; i++)
            {
                IPEndPoint iPEndPoint = array[i];
                bool flag = iPEndPoint.Port == port;
                if (flag)
                {
                    string[] expr_36 = new string[5];
                    expr_36[0] = "IP【";
                    int arg_53_1 = 1;
                    IPAddress expr_47 = iPEndPoint.Address;
                    expr_36[arg_53_1] = ((expr_47 != null) ? expr_47.ToString() : null);
                    expr_36[2] = "】port【";
                    expr_36[3] = iPEndPoint.Port.ToString();
                    expr_36[4] = "】"+crc.GetString("Res0044","已使用");
                    LogUtil.Error(string.Concat(expr_36));
                    result = true;
                    break;
                }
            }
            return result;
        }

        public bool IsOnline(string addr = "")
        {
           return isRun;
        }

        public string GetAddr()
        {
            return $"{string.Join(",", GetLocalAddresses())}:{serverPort}";
        }
    }

    /// <summary>
    /// 客户端会话信息类
    /// </summary>
    public class TcpClientBean
    {
        Socket m_clientSocket;
        public string IP = "";
        public string AddStr { get { return $"{IP}:{Port}"; } }
        public int Port = 0;

        public TcpClientBean() { }
        public void Close()
        {
            if (m_clientSocket != null && m_clientSocket.Connected)
            {
                m_clientSocket.Shutdown(SocketShutdown.Both);
                m_clientSocket.Close();
            }
        }
        public Socket ClientSocket
        {
            get { return m_clientSocket; }
            set { this.m_clientSocket = value; }
        }
    }
}