这是一个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) } } 范例代码下载