TcpServer.cs 9.4 KB
using OnlineStore;
using System;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Concurrent;

namespace OnlineStore.Common
{
    public class TcpServer
    {
      //  public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 接受消息时的间隔
        /// </summary>
        public static int ReviceMsgMS = 10;

        private Thread m_serverThread;
        private Socket m_serverSocket; 
        public delegate void ReviceMsg(TcpClientBean client, string Msg);
      
        public event ReviceMsg ReviceMsgEvent; 

        private delegate void ReceiveMessageDelegate(TcpClientBean client);

        public event AcceptClientDelegate AcceptClientEvent; 
        public delegate void AcceptClientDelegate(TcpClientBean client);
        ReceiveMessageDelegate receiveMessageDelegate;
        private bool isRun = true;
        private int serverPort = 0;
        private void logLocalIp()
        {
            string[] addresses = GetLocalAddresses();
            string iplist = $"本机IP"+":";
            if (addresses.Length > 0)
            {
                for (int i = 0; i < addresses.Length; i++)
                {
                    if (addresses.Length != 0)
                    {
                        iplist = iplist + " " + addresses[i];
                    }
                }
            }
            LogUtil.info( iplist + "]");
        }

        /// <summary>
        /// 开始服务
        /// </summary>
        public void Start(int m_serverPort)
        {
            try
            {
                isRun = true;
                m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, m_serverPort);
                this.serverPort = m_serverPort;
                m_serverSocket.Bind(localEndPoint);
                m_serverSocket.Listen(10);

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

                LogUtil.info( " Server start listen : " + m_serverPort);
                logLocalIp(); 

                //this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Server started.");
            }
            catch (SocketException se)
            {
                throw new Exception(se.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            try
            {
                isRun = false;
                m_serverThread.Interrupt(); // 线程终止
                m_serverSocket.Close(); // Socket Close  
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private void ReceiveAccept()
        {
            while (isRun)
            {
                TcpClientBean client = new TcpClientBean();
                try
                {
                    client.ClientSocket = m_serverSocket.Accept();
                    IPEndPoint clientipe = (IPEndPoint)client.ClientSocket.RemoteEndPoint;
                    client.AddStr = clientipe.Address.ToString()+":"+clientipe.Port.ToString();
                    LogUtil.info( "["+serverPort+"]有新的客户端链接上:[" + client.AddStr+"]"); 
                    AcceptClientEvent?.Invoke(client);

                    receiveMessageDelegate = new ReceiveMessageDelegate(ReceiveMessages);
                    receiveMessageDelegate.BeginInvoke(client, ReceiveMessagesCallback, "");
                }
                catch (Exception ex)
                {
                    LogUtil.error( "ReceiveAccept方法,客户端【"+client.AddStr+"】:" + ex.Message);
                    //throw new Exception(ex.Message);
                }
            }
        } 
        //   private StringBuilder sb = new StringBuilder();             //这个是用来保存:接收到了的,但是还没有结束的消息
        private int receiveBufferSize = 1024;
        private string terminateString = "\r";
        public void ReceiveMessages(TcpClientBean client)            //这个函数会被以线程方式运行
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                Socket socket = (Socket)client.ClientSocket;
                while (true)
                {
                    byte[] buffer = new byte[receiveBufferSize];  //buffer大小,此处为1024
                    int receivedSize = socket.Receive(buffer);
                    if (receivedSize > 0)
                    {
                        string rawMsg = Encoding.ASCII.GetString(buffer, 0, receivedSize);
                        int rnFixLength = terminateString.Length;   //这个是指消息结束符的长度,此处为\r\n
                        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());//找到了消息结束符,触发消息接收完成事件
                                    sb = new StringBuilder();
                                    i += rnFixLength;
                                }
                            }
                            else
                            {
                                sb.Append(rawMsg[i]);
                                i++;
                            }
                        }
                    }

                    Thread.Sleep(ReviceMsgMS);
                }
            }
            catch (SocketException e)
            {
                LogUtil.error("客户端{" + client.AddStr + "]:" + e.ToString(), 106);
            }
            catch (Exception ex)
            {
                LogUtil.error("客户端{" + client.AddStr + "]:" + ex.ToString(), 105);
            }
        }
        //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))
        //            {
        //                LogUtil.info(LOGGER, "收到数据:" + strReceiveData);
        //                // this.AddRunningInfo(">> Receive data from [" + client.ClientSocket.RemoteEndPoint.ToString()+ "]:" + strReceiveData);
        //                string strSendData = "OK. The content is:" + strReceiveData;
        //                //LogUtil.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)
        //    {
        //        LogUtil.error(LOGGER, e.ToString());
        //    }
        //    catch (Exception ex)
        //    {
        //        LOGGER.Error(ex.ToString());
        //    }
        //}

        private void ReceiveMessagesCallback(IAsyncResult AR)
        {
            try
            {
                receiveMessageDelegate.EndInvoke(AR);
            }
            catch (Exception ex)
            {
                LogUtil.error(ex.ToString());
            }
        }

        /// <summary>
        /// 获取本机地址列表
        /// </summary>
        public string[] GetLocalAddresses()
        {
            // 获取主机名
            string strHostName = Dns.GetHostName();

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

            string[] retval = new string[iphostentry.AddressList.Length];

            int i = 0;
            foreach (IPAddress ipaddress in iphostentry.AddressList)
            {
                if (ipaddress.AddressFamily != AddressFamily.InterNetworkV6)
                {
                    retval[i] = ipaddress.ToString();
                    i++;
                }
            }
            return retval;
        }
    }

    /// <summary>
    /// 客户端会话信息类
    /// </summary>
    public class TcpClientBean
    {
        Socket m_clientSocket;

        public TcpClientBean() { }
        public string AddStr = "";
        public Socket ClientSocket
        {
            get { return m_clientSocket; }
            set { this.m_clientSocket = value; }
        }
    }

}