您的位置:首页 > 其它

[.NET] WinCE与WindowsXP Client/Server通讯范例

2010-09-20 15:06 267 查看
这是一个TCP/IP的Socket范例代码

今年一月的时候接了一个项目

这个项目是要重新写过一个TCP/IP的Socket

并使用在WinCE与WindowsXP的通讯



Client Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using System.Collections;
/*
 *  Message Const rule:
 *  1. Message Type ID: 0-10 system message.
 *  2. 11~255: custom message.
 *  3. Handshake message: if you want to declare a handshake message, must like this sample.
 *    Sample:
 *     TYPE_COMMAND        = 14;
 *     TYPE_COMMAND_OK     = 15;
 *    Rule:
 *     handshake message = ID;
 *     handshake return OK = ID + 1;
 *  Testing report:
 *  1. disconnection testing.
 *      1-1. If client was shutdown server can handle it.
 *      1-2. if server shutdown, client must call connect again.
 *  2. Long data testing.
 *      Client send 200000 bytes data to server to test.
 */

namespace TcpObjectCE
{
    /// <summary>
    /// Const definition
    /// </summary>
    public class MessageConst
    {
        public const byte EOF_FLAG            = 0xFF;
        public const byte SERVER_ID           = 100;
        public const byte TYPE_CLIENT_ID      = 0; // byte array
        public const byte TYPE_SHUTDOWN       = 1; // byte array
        public const byte TYPE_UPDATE         = 11; // byte array
        public const byte TYPE_MESSAGE_BOX    = 12; // string
        public const byte TYPE_EVENT_LOG      = 13; // string
        public const byte TYPE_COMMAND        = 14; // string
        public const byte TYPE_COMMAND_OK     = 15; // string
        public const byte TYPE_AUTOMATION     = 16; // serialize string
        public const byte TYPE_AUTOMATION_OK  = 17; // string
    }

    public class MessageIDManager
    {
        static int MessageID = 1000;
        /// <summary>
        /// Get a serial number for message id.
        /// </summary>
        /// <returns>Message ID</returns>
        public static int GetMessageID()
        {
            if (MessageID >= 500000000)
                MessageID = 255;
            return MessageID++;
        }
    }
    /// <summary>
    /// Format message header for communication.
    /// </summary>
    public class MessageHeader
    {
        public const int MSG_HEADER_LENGTH = 11;
        // Header Length is 11 byte
        byte m_i1MessageType;  // byte [0]
        byte m_i1SourceID;     // byte [1]
        byte m_i1TargetID;     // byte [2]
        int m_i4MessageID;     // byte [3,4,5,6]
        int m_i4ContentLength; // byte [7,8,9,10]

        // Propertys
        public byte MessageType
        {
            get { return m_i1MessageType; }
            set { m_i1MessageType = value; }
        }

        public byte SourceID
        {
            get { return m_i1SourceID; }
            set { m_i1SourceID = value; }
        }

        public byte TargetID
        {
            get { return m_i1TargetID; }
            set { m_i1TargetID = value; }
        }

        public int MessageID
        {
            get { return m_i4MessageID; }
            set { m_i4MessageID = value; }
        }

        public int ContentLength
        {
            get { return m_i4ContentLength; }
            set { m_i4ContentLength = value; }
        }
    }
    /// <summary>
    /// Format message content for communication.
    /// </summary>
    public class MessageContent
    {
        MessageHeader m_pHeader;
        byte[]        m_bContent;
        DateTime      m_dtCheckTime; // using for check response

        private MessageContent() { }

        public override string  ToString()
        {
            return "Message:" + MessageID + " TargetID:" + TargetID;
        }
        /// <summary>
        /// MessageContent Conststruct,using for AnalyzeData
        /// </summary>
        /// <param name="a_bData">Data</param>
        /// <param name="a_i4Length">Data Length</param>
        public MessageContent(byte[] a_bData, int a_i4Length)
        {
            // using for data receive
            m_pHeader = new MessageHeader();
            MessageType = a_bData[0];
            SourceID = a_bData[1];
            TargetID = a_bData[2];
            MessageID = BitConverter.ToInt32(a_bData,3);
            ContentLength = BitConverter.ToInt32(a_bData, 7);
            if (ContentLength > a_i4Length)
                throw new Exception("Content Error!");
            if (ContentLength == 0)
                throw new Exception("Format Error!");
            Content = new byte[ContentLength];
            Array.Copy(a_bData, MessageHeader.MSG_HEADER_LENGTH, Content, 0, ContentLength);
        }
        /// <summary>
        /// MessageContent Conststruct,using for return handshake message.
        /// </summary>
        /// <param name="a_i1MessageType">Message Type</param>
        /// <param name="a_i4MessageID">Message ID</param>
        /// <param name="a_i1SourceID">Source ID</param>
        /// <param name="a_i1TargetID">Target ID</param>
        /// <param name="a_bContent">Data</param>
        public MessageContent(byte a_i1MessageType,int a_i4MessageID,
            byte a_i1SourceID, byte a_i1TargetID, byte[] a_bContent)
        {
            // using for send data
            m_pHeader = new MessageHeader();
            MessageType = a_i1MessageType;
            SourceID = a_i1SourceID;
            TargetID = a_i1TargetID;
            Content = a_bContent;
            MessageID = a_i4MessageID;
            ContentLength = Content.Length;
        }
        /// <summary>
        /// MessageContent Conststruct
        /// </summary>
        /// <param name="a_i1MessageType">Message Type</param>
        /// <param name="a_i1SourceID">Source ID</param>
        /// <param name="a_i1TargetID">Target ID</param>
        /// <param name="a_bContent">Data</param>
        public MessageContent(byte a_i1MessageType, byte a_i1SourceID, byte a_i1TargetID, byte[] a_bContent)
        {
            // using for send data
            m_pHeader = new MessageHeader();
            MessageType = a_i1MessageType;
            SourceID = a_i1SourceID;
            TargetID = a_i1TargetID;
            Content = a_bContent;
            MessageID = MessageIDManager.GetMessageID();
            ContentLength = Content.Length;
        }
        /// <summary>
        /// Get MessageContent total length
        /// (content length + header length(11 bytes) + EOF length(1 byte))
        /// </summary>
        public int TotalLength
        {
            // content length + header length + EOF length
            get { return ContentLength + MessageHeader.MSG_HEADER_LENGTH + 1; }
        }
        /// <summary>
        /// Convert MessageContent object to byte array
        /// </summary>
        /// <returns>byte array</returns>
        public byte[] GetBytes()
        {
            // total size is header length(11 bytes) + content length + end flag(1 byte)
            byte[] t_bData = new byte[ContentLength + MessageHeader.MSG_HEADER_LENGTH + 1];
            t_bData[0] = MessageType;
            t_bData[1] = SourceID;
            t_bData[2] = TargetID;
            Array.Copy(BitConverter.GetBytes(MessageID), 0, t_bData, 3, 4);
            Debug.WriteLine(BitConverter.ToString(t_bData, 3, 4));
            Debug.WriteLine(BitConverter.ToInt32(t_bData, 3));
            Array.Copy(BitConverter.GetBytes(ContentLength), 0, t_bData, 7, 4);
            Debug.WriteLine(BitConverter.ToString(t_bData, 7, 4));
            Debug.WriteLine(BitConverter.ToInt32(t_bData, 7));
            Array.Copy(Content, 0, t_bData, MessageHeader.MSG_HEADER_LENGTH, ContentLength);
            Debug.WriteLine(BitConverter.ToString(t_bData, MessageHeader.MSG_HEADER_LENGTH, ContentLength));
            Array.Copy(new byte[] { MessageConst.EOF_FLAG }, 0, t_bData, MessageHeader.MSG_HEADER_LENGTH + ContentLength, 1);

            return t_bData;
        }

        /// <summary>
        /// Set Message Type
        /// </summary>
        public byte MessageType
        {
            get { return m_pHeader.MessageType; }
            set { m_pHeader.MessageType = value; }
        }

        public byte SourceID
        {
            get { return m_pHeader.SourceID; }
            set { m_pHeader.SourceID = value; }
        }

        public byte TargetID
        {
            get { return m_pHeader.TargetID; }
            set { m_pHeader.TargetID = value; }
        }

        public int MessageID
        {
            get { return m_pHeader.MessageID; }
            set { m_pHeader.MessageID = value; }
        }

        public int ContentLength
        {
            get { return m_pHeader.ContentLength; }
            set { m_pHeader.ContentLength = value; }
        }

        public byte[] Content
        {
            get { return m_bContent; }
            set { m_bContent = value; }
        }

        public DateTime CheckTime
        {
            get { return m_dtCheckTime; }
            set { m_dtCheckTime = value; }
        }
        /// <summary>
        /// Get String Content
        /// </summary>
        public string MsgContent
        {
            get { return ASCIIEncoding.ASCII.GetString(Content, 0, ContentLength); }
        }
    }
    /// <summary>
    /// TCP IP Client
    /// </summary>
    public class MTCPIPClient
    {
        public const int LOG_LEVEL_DEBUG   = 0;
        public const int LOG_LEVEL_TRACE   = 1;
        public const int LOG_LEVEL_NORMAL  = 2;
        public const int LOG_LEVEL_WARRING = 3;

        string    m_sIP;
        int       m_i4Port;
        string    m_sTargetName;
        byte      m_i1ClientID;
        Socket    m_pClient;
        bool      m_bIsConnected;
        Thread    m_pReceiveThread;
        Thread    m_pHandshakeThread;
        ArrayList m_pMsgHandshakeList;

        /// <summary>
        /// Trace Log Event Delegate.
        /// </summary>
        /// <param name="a_i4Level">Log level</param>
        /// <param name="a_sLog">Log</param>
        public delegate void TraceLogHanlder(int a_i4Level,string a_sLog);

        /// <summary>
        /// MessageContent object event delegate.
        /// </summary>
        /// <param name="a_pMsg">MessageContent object</param>
        public delegate void MessageContentHanlder(MessageContent a_pMsg);
        
        /// <summary>
        /// Client shutdown Event Delegate.
        /// </summary>
        /// <param name="a_i1ClientID">Client ID</param>
        public delegate void ClientShutdownHanlder(byte a_i1ClientID);

        /// <summary>
        /// Client shutdown event.
        /// </summary>
        public event ClientShutdownHanlder EventClientShutdown;
        /// <summary>
        /// Log event.
        /// </summary>
        public event TraceLogHanlder EventTraceLog;
        /// <summary>
        /// To arisr this event, when receive data.
        /// </summary>
        public event MessageContentHanlder EventDataReceive;
        /// <summary>
        /// To arisr this event, when a handshake event timeout 3 sec.
        /// </summary>
        public event MessageContentHanlder EventHandshakeFail;

        public byte ClientID
        {
            get { return m_i1ClientID; }
        }

        public string TargetName
        {
            get { return m_sTargetName; }
        }

        public bool IsConnected
        {
            get { return m_bIsConnected; }
        }

        /// <summary>
        /// Trace Log
        /// </summary>
        /// <param name="a_i4Level">Log level</param>
        /// <param name="a_sLog">Log content</param>
        private void TraceLog(int a_i4Level,string a_sLog)
        {
            if (EventTraceLog != null)
            {
                EventTraceLog(a_i4Level, "[Client ID]:" + ClientID + " To [" + TargetName + "]," + a_sLog);
            }
        }

        private MTCPIPClient() { }

        /// <summary>
        /// MTCPIPClient consturct
        /// </summary>
        /// <param name="a_i1ClientID">Client ID</param>
        public MTCPIPClient(byte a_i1ClientID)
        {
            m_bIsConnected = false;
            m_i1ClientID = a_i1ClientID;
            m_sTargetName = "No Target";
            m_pMsgHandshakeList = new ArrayList();
        } // end of MTCPIPClient(string a_sClientID)

        /// <summary>
        /// MTCPIPClient consturct
        /// </summary>
        /// <param name="a_i1ClientID">Client ID</param>
        /// <param name="a_sTargetName">Target Name</param>
        /// <param name="a_sIP">Remote IP</param>
        /// <param name="a_i4Port">Remote Port</param>
        public MTCPIPClient(byte a_i1ClientID,string a_sTargetName, string a_sIP, int a_i4Port)
        {
            m_bIsConnected = false;
            m_i1ClientID = a_i1ClientID;
            m_sTargetName = a_sTargetName;
            m_sIP = a_sIP;
            m_i4Port = a_i4Port;
            m_pMsgHandshakeList = new ArrayList();
        } // end of MTCPIPClient(byte a_i1ClientID,string a_sIP,int a_i4Port)

        /// <summary>
        /// MTCPIPClient consturct, using for server accept a new client
        /// </summary>
        /// <param name="a_pClient">Socket Client</param>
        /// <param name="a_i1ClientID">Client ID</param>
        public MTCPIPClient(Socket a_pClient, byte a_i1ClientID)
        {
            // New MTCPClient
            // using by server
            m_bIsConnected = false;
            m_pClient = a_pClient;
            m_i1ClientID = a_i1ClientID;
            m_sTargetName = "Client";
            m_pMsgHandshakeList = new ArrayList();
        } // end of MTCPIPClient(Socket a_pClient, string a_sClientID)
        ~MTCPIPClient()
        {
            Shutdown();
        } // end of ~MTCPIPClient()

        /// <summary>
        /// Get MTCPClient information
        /// </summary>
        /// <returns>RemoteEndPoint + Client ID</returns>
        public override string  ToString()
        {
            return m_pClient.RemoteEndPoint.ToString() + ",Client ID:" + ClientID;
        } // end of ToString()

        /// <summary>
        /// Connect to server without set Client ID and start receive.
        /// </summary>
        public void NormalConnect()
        {
            try
            {
                if (!IsConnected)
                {
                    // new TCP/IP Socket
                    m_pClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    // connect to server
                    m_pClient.Connect(new IPEndPoint(IPAddress.Parse(m_sIP), m_i4Port));
                    TraceLog(LOG_LEVEL_TRACE, "Connect to " + m_sIP + ":" + m_i4Port + " success.");
                    // Start Receive Data
                    StartReceive();
                } // end if(!m_bIsConnected)
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [Connect]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [Connect]", ex.NativeErrorCode, ex.Message));
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " In [Connect]");
                TraceLog(LOG_LEVEL_DEBUG,String.Format("[Exception]:{0} In [Connect]", ex.Message));
                throw;
            }
        }
        /// <summary>
        /// Conect to server and set Client ID to server and start receive.
        /// </summary>
        public void Connect()
        {
            try
            {
                if (!IsConnected)
                {
                    // new TCP/IP Socket
                    m_pClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    // connect to server
                    m_pClient.Connect(new IPEndPoint(IPAddress.Parse(m_sIP), m_i4Port));
                    TraceLog(LOG_LEVEL_NORMAL, "Connect to " + m_sIP + ":" + m_i4Port + " success.");
                    // create ID Message
                    MessageContent t_pMsg = new MessageContent(MessageConst.TYPE_CLIENT_ID, ClientID, MessageConst.SERVER_ID, new byte[] { ClientID });
                    // send ID to server
                    m_pClient.Send(t_pMsg.GetBytes());
                    TraceLog(LOG_LEVEL_NORMAL, "Send Client ID:" + ClientID + " success");
                    // Start Receive Data
                    StartReceive();
                } // end if(!m_bIsConnected)
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [Connect]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [Connect]", ex.NativeErrorCode, ex.Message));
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " In [Connect]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [Connect]", ex.Message));
                throw;
            }
        } // end of Connect()

        /// <summary>
        /// Conect to server and set Client ID to server and start receive.
        /// If using no parameter construct, can call this function.
        /// </summary>
        /// <param name="a_sIP">Remote IP</param>
        /// <param name="a_i4Port">Remote Port</param>
        public void Connect(string a_sIP, int a_i4Port)
        {
            m_sIP = a_sIP;
            m_i4Port = a_i4Port;
            Connect();
            
        } // end of Connect(string a_sIP, int a_i4Port)

        /// <summary>
        /// Send Message without MessageContent object.
        /// </summary>
        /// <param name="a_sMsgContent">Text data content</param>
        public void SendNormalMessage(string a_sMsgContent)
        {
            try
            {
                m_pClient.Send(ASCIIEncoding.ASCII.GetBytes(a_sMsgContent));
            }
            catch (SocketException ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [SendNormalMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [SendNormalMessage]", ex.NativeErrorCode, ex.Message));
            }
            catch (Exception ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.Message + " In [SendNormalMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [SendNormalMessage]", ex.Message));
            }
        } // emd of SendNormalMessage(string a_sMsgContent)

        /// <summary>
        /// Send message with MessageContent object.
        /// </summary>
        /// <param name="a_i1MsgType">Message type</param>
        /// <param name="a_sMsgContent">Text data content</param>
        public void SendMessage(byte a_i1MsgType, string a_sMsgContent)
        {
            try
            {
                // send string data to server(FrontEnd or MainFrame)
                MessageContent t_pMsg = new MessageContent(a_i1MsgType,
                    ClientID, MessageConst.SERVER_ID, Encoding.ASCII.GetBytes(a_sMsgContent));

                m_pClient.Send(t_pMsg.GetBytes());
                AddHandshakeMessage(t_pMsg);
            }
            catch (SocketException ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [SendMessage]", ex.NativeErrorCode, ex.Message));
            }
            catch (Exception ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [SendMessage]", ex.Message));
            }
        } // emd of SendMessage(int a_i4MsgID, string a_sMsg)

        /// <summary>
        /// Send message with MessageContent object.
        /// </summary>
        /// <param name="a_i1MsgType">Message type</param>
        /// <param name="a_bContent">Binary data content</param>
        public void SendMessage(byte a_i1MsgType, byte[] a_bContent)
        {
            try
            {
                // send byte array data to server(FrontEnd or MainFrame)
                MessageContent t_pMsg = new MessageContent(a_i1MsgType,
                    ClientID, MessageConst.SERVER_ID, a_bContent);

                m_pClient.Send(t_pMsg.GetBytes());
                AddHandshakeMessage(t_pMsg);
            }
            catch (SocketException ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [SendMessage]", ex.NativeErrorCode, ex.Message));
            }
            catch (Exception ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [SendMessage]", ex.Message));
            }
        } // emd of SendMessage(int a_i4MsgID, byte[] a_bContent)

        /// <summary>
        /// Send message with MessageContent object.
        /// </summary>
        /// <param name="a_pMsg">MessageContent object</param>
        public void SendMessage(MessageContent a_pMsg)
        {
            try
            {
                // send data with MessageContent
                m_pClient.Send(a_pMsg.GetBytes());
                AddHandshakeMessage(a_pMsg);
            }
            catch (SocketException ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [SendMessage]", ex.NativeErrorCode, ex.Message));
            }
            catch (Exception ex)
            {
                m_bIsConnected = false;
                Debug.WriteLine(ex.Message + " In [SendMessage]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [SendMessage]", ex.Message));
            }
        } // emd of SendMessage(MessageContent a_pMsg)

        /// <summary>
        /// Add message type MessageConst.TYPE_COMMAND and MessageConst.TYPE_AUTOMATION
        /// to handshake checking.
        /// </summary>
        /// <param name="a_pMsg">MessageContent object</param>
        void AddHandshakeMessage(MessageContent a_pMsg)
        {
            if (a_pMsg.MessageType == MessageConst.TYPE_COMMAND ||
                a_pMsg.MessageType == MessageConst.TYPE_AUTOMATION)
            {
                a_pMsg.CheckTime = DateTime.Now;
                m_pMsgHandshakeList.Add(a_pMsg);
            }
        } // end of AddHandshakeMessage(MessageContent a_pMsg)

        /// <summary>
        /// Check receive message is or not handshake message.
        /// </summary>
        /// <param name="a_pMsg">MessageContent object</param>
        void CheckHandshakeMessage(MessageContent a_pMsg)
        {
            if (a_pMsg.MessageType == MessageConst.TYPE_COMMAND ||
                a_pMsg.MessageType == MessageConst.TYPE_AUTOMATION)
            {
                // if receive a COMMAND or AUTOMATION
                // response a OK handshake
                MessageContent t_pMsg = new MessageContent((byte)(a_pMsg.MessageType + 1),a_pMsg.MessageID,
                    a_pMsg.TargetID, a_pMsg.SourceID, ASCIIEncoding.ASCII.GetBytes("OK"));
                SendMessage(t_pMsg);
                return;
            }
            if (m_pMsgHandshakeList.Count == 0)
                return;
            if (a_pMsg.MessageType == MessageConst.TYPE_COMMAND_OK ||
                a_pMsg.MessageType == MessageConst.TYPE_AUTOMATION_OK)
            {
                for (int i = 0; i < m_pMsgHandshakeList.Count; i++)
                {
                    MessageContent t_pHandshakeMsg = (MessageContent)m_pMsgHandshakeList[i];
                    if (t_pHandshakeMsg.MessageID == a_pMsg.MessageID)
                    {
                        m_pMsgHandshakeList.RemoveAt(i);
                        break;
                    }
                } // end for
            }
        } // end of CheckHandshakeMessage(MessageContent a_pMsg)

        /// <summary>
        /// Shutdown client.
        /// </summary>
        public void Shutdown()
        {
            try
            {
                m_bIsConnected = false;
                if (m_pClient != null)
                {
                    m_pClient.Shutdown(SocketShutdown.Both);
                    m_pClient.Close();
                    m_pClient = null;
                }
                TraceLog(LOG_LEVEL_TRACE, "Connection shutdown success.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [Shutdown]", ex.Message));
            }
        } // end of Shutdown()

        /// <summary>
        /// Disconect the connection.
        /// </summary>
        public void Disconnect()
        {
            try
            {
                if (m_pClient != null)
                {
                    MessageContent t_pMsg = new MessageContent(MessageConst.TYPE_SHUTDOWN,
                        ClientID, MessageConst.SERVER_ID, ASCIIEncoding.ASCII.GetBytes("ByeBye"));
                    SendMessage(t_pMsg);
                }
                Shutdown();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " In [Disconnect]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [Disconnect]", ex.Message));
            }
        } // end of Disconnect()

        /// <summary>
        ///Start Receive data and Handshake's thread.
        /// </summary>
        public void StartReceive()
        {
            if ( m_pReceiveThread != null )
            {
                try
                {
                    m_pReceiveThread.Abort();
                    m_pReceiveThread = null;
                }
                catch (Exception) { }
            }
            if (m_pHandshakeThread != null)
            {
                try
                {
                    m_pHandshakeThread.Abort();
                    m_pHandshakeThread = null;
                }
                catch (Exception) { }
            }
            m_pReceiveThread = new Thread(new ThreadStart(this.ReceiveData));
            m_pReceiveThread.Name = m_i1ClientID.ToString();
            m_pReceiveThread.Start();
            m_bIsConnected = true;
            m_pHandshakeThread = new Thread(new ThreadStart(this.HandshakeData));
            m_pHandshakeThread.Name = m_i1ClientID.ToString();
            m_pHandshakeThread.Start();
        } // end of StartReceive()

        /// <summary>
        /// Analyze Client ID
        /// </summary>
        /// <param name="a_bData">Receive data content</param>
        /// <param name="a_i4Length">Receive data length</param>
        /// <returns>MessageContent object</returns>
        public static MessageContent AnalyzeClientID(byte[] a_bData, int a_i4Length)
        {
            MessageContent t_pMsg = new MessageContent(a_bData, a_i4Length);
            return t_pMsg;
        }

        /// <summary>
        /// Analyze data when receive one or more package.
        /// </summary>
        /// <param name="a_bData">Receive data content</param>
        /// <param name="a_i4Length">Receive data length</param>
        private void AnalyzeData(byte[] a_bData,int a_i4Length)
        {
            try
            {
                while(true)
                {
                    if (a_i4Length <= MessageHeader.MSG_HEADER_LENGTH)
                        return;
                    MessageContent t_pMsg = new MessageContent(a_bData, a_i4Length);
                    if (t_pMsg.MessageType == MessageConst.TYPE_SHUTDOWN)
                    {
                        if (EventClientShutdown != null)
                            EventClientShutdown(this.ClientID);
                        Shutdown();
                        return;
                    } // end if
                    else
                    {
                        // Handshake check
                        CheckHandshakeMessage(t_pMsg);
                        // Event Receive data
                        if (EventDataReceive != null)
                            EventDataReceive(t_pMsg);
                    } // end else
                    if (t_pMsg.TotalLength == a_i4Length)
                    {
                        break;
                    }
                    else
                    {
                        // remnant data
                        Debug.WriteLine(BitConverter.ToString(a_bData, 0, a_i4Length));
                        Array.Copy(a_bData, t_pMsg.TotalLength, a_bData, 0, a_i4Length);
                        Debug.WriteLine(BitConverter.ToString(a_bData, 0, a_i4Length));
                        a_i4Length = a_i4Length - t_pMsg.TotalLength;
                    }
                }// end for
            }
            catch (Exception ex)
            {
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [AnalyzeData]", ex.Message));
            }
        }// end of AnalyzeData(byte[] a_bData,int a_i4Length)

        /// <summary>
        /// Using for Receive data with Thread.
        /// </summary>
        private void ReceiveData()
        {
            try
            {
                // Receive Loop
                while (IsConnected)
                {
                    byte[] t_bData = new byte[204800];
                    int t_i4Length = m_pClient.Receive(t_bData);
                    if (t_i4Length > 0)
                    {
                        AnalyzeData(t_bData,t_i4Length);
                    }
                    if (t_i4Length == 0)
                    {
                        Shutdown();
                        break;
                    }
                    Thread.Sleep(1);
                }
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message + " In [ReceiveData]");
                // 遠端強制關閉連線,則關閉本身資源並釋放
                TraceLog(LOG_LEVEL_NORMAL, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [ReceiveData]", ex.NativeErrorCode, ex.Message));
                if (EventClientShutdown != null)
                    EventClientShutdown(this.ClientID);
                Shutdown();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " In [ReceiveData]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [ReceiveData]", ex.Message));
                if (EventClientShutdown != null)
                    EventClientShutdown(this.ClientID);
                Shutdown();
            }
        } // end of ReceiveData()

        /// <summary>
        /// Using for Handshake message checking with Thread.
        /// </summary>
        private void HandshakeData()
        {
            try
            {
                Debug.WriteLine("Handshake thread start!!!!!!");
                // Handshake Loop
                while (IsConnected)
                {
                    if (m_pMsgHandshakeList.Count > 0)
                    {
                        Monitor.Enter(m_pMsgHandshakeList);
                        for (int i = 0; i < m_pMsgHandshakeList.Count; i++)
                        {
                            MessageContent t_pHandshakeMsg = (MessageContent)m_pMsgHandshakeList[i];
                            TimeSpan t_IdleTime = DateTime.Now.Subtract(t_pHandshakeMsg.CheckTime);
                            if (t_IdleTime.TotalSeconds >= 3)
                            {
                                Debug.WriteLine("Message:" + t_pHandshakeMsg.MessageID + " idle!");
                                // Idle 3 secounds
                                if (EventHandshakeFail != null)
                                    EventHandshakeFail(t_pHandshakeMsg);
                                m_pMsgHandshakeList.RemoveAt(i);
                                break;
                            }
                        } // end for
                        Monitor.Exit(m_pMsgHandshakeList);
                    }
                    Thread.Sleep(500);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " In [HandshakeData]");
                TraceLog(LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [HandshakeData]", ex.Message));
            }
        } // end of HandshakeData()
    }
}




Server Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.Diagnostics;

/*
 *  Design rule:
 *  1. Server only handle one ID of Client.
 *  2. If Client ID duplicate server will release old Client, and handle new client.
 */

namespace TcpObjectCE
{
    public class MTCPIPServer
    {
        string    m_sIP;
        int       m_i4Port;
        Socket    m_pServer;
        ArrayList m_pClientList;
        Thread    m_pAcceptThread;
        bool      m_bIsRunning;

        public event MTCPIPClient.TraceLogHanlder EventTraceLog;
        public event MTCPIPClient.MessageContentHanlder EventAllClientReceive;
        public event MTCPIPClient.MessageContentHanlder EventAllClientHandshakeFail;

        /// <summary>
        /// Trace Log
        /// </summary>
        /// <param name="a_i4Level">Log level</param>
        /// <param name="a_sLog">Log content</param>
        private void TraceLog(int a_i4Level,string a_sLog)
        {
            if (EventTraceLog != null)
            {
                EventTraceLog(a_i4Level,"[Server]:" + a_sLog);
            }
        }

        /// <summary>
        /// MTCPIPServer construct.
        /// </summary>
        /// <param name="a_sIP">Server IP</param>
        /// <param name="a_i4Port">Server Port</param>
        public MTCPIPServer(string a_sIP, int a_i4Port)
        {
            m_sIP = a_sIP;
            m_i4Port = a_i4Port;
            m_pClientList = new ArrayList();
        } // end of MTCPIPServer(string a_sIP, int a_i4Port)
        ~MTCPIPServer()
        {
            ShutdownServer();
        } // end of ~MTCPIPServer()

        /// <summary>
        /// Check Client is connected
        /// </summary>
        /// <param name="a_i4ClientID">Client ID</param>
        /// <returns>true is connected</returns>
        public bool CheckClientConnected(int a_i4ClientID)
        {
            if (m_pClientList.Count == 0)
                return false;
            for (int t_i4ClientIndex = 0; t_i4ClientIndex < m_pClientList.Count; t_i4ClientIndex++)
            {
                MTCPIPClient t_pTcpClient = (MTCPIPClient)m_pClientList[t_i4ClientIndex];
                if (t_pTcpClient.ClientID == (byte)a_i4ClientID)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Start server
        /// </summary>
        public void StartServer()
        {
            try
            {
                m_pServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                // connect to server
                m_pServer.Bind(new IPEndPoint(IPAddress.Parse(m_sIP), m_i4Port));
                m_pServer.Listen(100);
                TraceLog(MTCPIPClient.LOG_LEVEL_NORMAL, "Bind to" + m_sIP + ":" + m_i4Port + " success.");
                if (m_pAcceptThread != null)
                {
                    m_pAcceptThread.Abort();
                    m_pAcceptThread = null;
                }
                m_pAcceptThread = new Thread(new ThreadStart(this.AcceptClient));
                m_pAcceptThread.Name = "ServerAccept";
                m_bIsRunning = true;
                m_pAcceptThread.Start();
                TraceLog(MTCPIPClient.LOG_LEVEL_NORMAL, "Start Accept.");
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_WARRING, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [StartServer]", ex.NativeErrorCode, ex.Message));
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_WARRING, String.Format("[Exception]:{0} In [StartServer]", ex.Message));
                throw;
            }
        } // end of  StartServer()

        /// <summary>
        /// Shutdown server.
        /// </summary>
        public void ShutdownServer()
        {
            try
            {
                for (int t_i4ClientIndex = 0; t_i4ClientIndex < m_pClientList.Count; t_i4ClientIndex++)
                {
                    MTCPIPClient t_pShutDownTcpClient = (MTCPIPClient)m_pClientList[t_i4ClientIndex];
                    try
                    {
                        t_pShutDownTcpClient.Shutdown();
                    }
                    catch (Exception) { }
                }
                if (m_pServer != null)
                {
                    m_pServer.Close();
                    m_pServer = null;
                }
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            try
            {
                m_bIsRunning = false;
                if (m_pAcceptThread != null)
                {
                    m_pAcceptThread.Abort();
                    m_pAcceptThread = null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            TraceLog(MTCPIPClient.LOG_LEVEL_TRACE, "Shutdown success");
        } // end of ShutdownServer()

        /// <summary>
        /// Accept client with Thread.
        /// </summary>
        void AcceptClient()
        {
            try
            {
                while (m_bIsRunning)
                {
                    Socket t_pNewClient = m_pServer.Accept();
                    byte[] t_bData = new byte[1024];
                    int t_i4Length = t_pNewClient.Receive(t_bData);
                    if (t_i4Length > 0)
                    {
                        MessageContent t_pMsg = MTCPIPClient.AnalyzeClientID(t_bData, t_i4Length);
                        byte t_i1ClientID = t_pMsg.Content[0];
                        MTCPIPClient t_pNewTcpClient = new MTCPIPClient(t_pNewClient, t_i1ClientID);
                        TraceLog(MTCPIPClient.LOG_LEVEL_NORMAL,t_pNewTcpClient.ToString() + " Connected");
                        t_pNewTcpClient.EventDataReceive += new MTCPIPClient.MessageContentHanlder(TcpClient_EventDataReceive);
                        t_pNewTcpClient.EventHandshakeFail += new MTCPIPClient.MessageContentHanlder(TcpClient_EventHandshakeFail);
                        t_pNewTcpClient.EventClientShutdown += new MTCPIPClient.ClientShutdownHanlder(TcpClient_EventClientShutdown);
                        t_pNewTcpClient.EventTraceLog += new MTCPIPClient.TraceLogHanlder(TraceLog);
                        t_pNewTcpClient.StartReceive();
                        AddNewClient(t_pNewTcpClient);
                    }
                    Thread.Sleep(1);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_DEBUG,String.Format("[Exception]:{0} In [AcceptClient]", ex.Message));
            }
        } // end of AcceptClient()

        /// <summary>
        /// Add new client for list when accept a client.
        /// If client already exist,to shutdown the old exist client and to handle the new client.
        /// </summary>
        /// <param name="t_pNewClient">New Client</param>
        void AddNewClient(MTCPIPClient t_pNewClient)
        {
            for (int t_i4ClientIndex = 0; t_i4ClientIndex < m_pClientList.Count; t_i4ClientIndex++)
            {
                MTCPIPClient t_pExistTcpClient = (MTCPIPClient)m_pClientList[t_i4ClientIndex];
                if (t_pExistTcpClient.ClientID.Equals(t_pNewClient.ClientID))
                {
                    t_pExistTcpClient.Shutdown();
                    m_pClientList.Remove(t_pExistTcpClient);
                    t_pExistTcpClient = null;
                    break;
                }
            }
            m_pClientList.Add(t_pNewClient);
        }

        /// <summary>
        /// delegate function, using for MTCPIPClient.EventClientShutdown
        /// </summary>
        /// <param name="a_i1ClientID">Shutdown client Id</param>
        void TcpClient_EventClientShutdown(byte a_i1ClientID)
        {
            MTCPIPClient t_pShutDownTcpClient = null;
            try
            {
                bool t_bIsFoundTarget = false;
                for (int t_i4ClientIndex = 0; t_i4ClientIndex < m_pClientList.Count; t_i4ClientIndex++)
                {
                    t_pShutDownTcpClient = (MTCPIPClient)m_pClientList[t_i4ClientIndex];
                    if (t_pShutDownTcpClient.ClientID == a_i1ClientID)
                    {
                        t_bIsFoundTarget = true;
                        break;
                    }
                }
                if (!t_bIsFoundTarget)
                {
                    throw new Exception("Client is not exist");
                }
                m_pClientList.Remove(t_pShutDownTcpClient);
                TraceLog(MTCPIPClient.LOG_LEVEL_NORMAL, t_pShutDownTcpClient.ToString() + " disconnected");
                t_pShutDownTcpClient = null;
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [TcpClient_EventClientShutdown]", ex.NativeErrorCode, ex.Message));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [TcpClient_EventClientShutdown]", ex.Message));
            }
        } // end of TcpClient_EventClientShutdown()

        /// <summary>
        /// delegate function, using for MTCPIPClient.EventHandshakeFail
        /// </summary>
        /// <param name="a_pMsg">MessageContent object.</param>
        void TcpClient_EventHandshakeFail(MessageContent a_pMsg)
        {
            if (EventAllClientHandshakeFail != null)
            {
                EventAllClientHandshakeFail(a_pMsg);
            }
        } // end of TcpClient_EventDataReceive()

        /// <summary>
        /// delegate function, using for MTCPIPClient.EventDataReceive
        /// </summary>
        /// <param name="a_pMsg">MessageContent object.</param>
        void TcpClient_EventDataReceive(MessageContent a_pMsg)
        {
            if (EventAllClientReceive != null)
            {
                EventAllClientReceive(a_pMsg);
            }
        } // end of TcpClient_EventDataReceive()

        /// <summary>
        /// Send text data to appoint client.
        /// </summary>
        /// <param name="a_i1ClientID">Appoint client</param>
        /// <param name="a_i1MsgType">Message Type</param>
        /// <param name="a_sMsgContent">Text data content</param>
        public void SendDataToClient(byte a_i1ClientID, byte a_i1MsgType, string a_sMsgContent)
        {
            MTCPIPClient t_pTargetTcpClient = null;
            try
            {
                bool t_bIsFoundTarget = false;
                for (int t_i4ClientIndex = 0; t_i4ClientIndex < m_pClientList.Count; t_i4ClientIndex++)
                {
                    t_pTargetTcpClient = (MTCPIPClient)m_pClientList[t_i4ClientIndex];
                    if (t_pTargetTcpClient.ClientID == a_i1ClientID)
                    {
                        t_bIsFoundTarget = true;
                        break;
                    }
                }
                if (!t_bIsFoundTarget)
                {
                    throw new Exception("Client is not exist");
                }
                MessageContent t_pMsg = new MessageContent(a_i1MsgType,
                    MessageConst.SERVER_ID, a_i1ClientID, Encoding.ASCII.GetBytes(a_sMsgContent));
                t_pTargetTcpClient.SendMessage(t_pMsg);
            }
            catch (SocketException ex)
            {
                Debug.WriteLine(ex.NativeErrorCode + ":" + ex.Message);
                Debug.WriteLine("Remove " + t_pTargetTcpClient.ToString());
                TraceLog(MTCPIPClient.LOG_LEVEL_DEBUG, String.Format("[ErrorCode]:{0},[SocketException]:{1} In [SendDataToClient]", ex.NativeErrorCode, ex.Message));
                // if got socket exception, release client
                m_pClientList.Remove(t_pTargetTcpClient);
                t_pTargetTcpClient.Shutdown();
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                TraceLog(MTCPIPClient.LOG_LEVEL_DEBUG, String.Format("[Exception]:{0} In [SendDataToClient]", ex.Message));
                throw;
            }
        } // end of SendDataToClient(string a_sClientID,int a_i4MsgID, string a_sMsg)
    }
}




范例代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: