服務端代碼,包含遠程客戶端類、服務端類、UI。
//遠程客戶端類
class RemoteClient { public TcpClient client{get; private set;} public BinaryReader br{get; private set;} public BinaryWriter bw{get; private set;} public string userName {get; set; } public RemoteClient(TcpClient client) { this.client = client; NetworkStream networkStream = client.GetStream(); br = new BinaryReader(networkStream); bw = new BinaryWriter(networkStream); this.userName = (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString() + ":"+(client.Client.RemoteEndPoint as IPEndPoint).Port.ToString(); } public void Close() { br.Close(); bw.Close(); client.Close(); } }
/// <summary> /// 服務器的類 /// </summary> class _TcpServer { //遠程客戶端對象集合 List<RemoteClient> remoteClientList = new List<RemoteClient>(); private TcpListener tcpServer; public _TcpServer(string localIP,int port) { /// <summary>使用的本機IP地址</summary> IPAddress localAddress = IPAddress.Parse(localIP); tcpServer = new TcpListener(localAddress, port); tcpServer.Start(); //創建一個線程監聽客戶端連接請求 Thread myThread = new Thread(ListenClientConnect); myThread.Start(); } /// <summary>接收客戶端連接</summary> private void ListenClientConnect() { TcpClient newClient = null; while (true) { try { newClient = tcpServer.AcceptTcpClient(); } catch { //當單擊“停止監聽”或者退出此窗體時AcceptTcpClient()會產生異常 //因此可以利用此異常退出循環 break; } //每接受一個客戶端連接,就創建一個對應的線程循環接收該客戶端發來的信息 RemoteClient user = new RemoteClient(newClient); Thread threadReceive = new Thread(ReceiveData); threadReceive.Start(user); remoteClientList.Add(user); ClassVar.WriteLogCommon(Environment.NewLine + "有遠程主機連接到本機,遠程主機信息:"+user.userName); } } /// <summary> /// 處理接收的客戶端數據 /// </summary> /// <param name="userState">客戶端信息</param> private void ReceiveData(object userState) { RemoteClient user = userState as RemoteClient; TcpClient client = user.client; while (true) { byte[] BytesLenth = null; byte[] BytesContent = null; try { if (user == null || user.br == null || user.client.Connected == false) { break; } BytesLenth = user.br.ReadBytes(2); int lenth = BitConverter.ToInt16(BytesLenth, 0); BytesContent = user.br.ReadBytes(lenth - 2); string conContent = Encoding.Default.GetString(BytesContent); //如果收到是心跳信息 if (conContent == "0000") { lock (ClassVar.frmMain.objTimeSpan) { ClassVar.frmMain.timeSpan = 0; } ClassVar.WriteLogCommonXT(Environment.NewLine + "收到心跳消息"); } //如果是警情信息則加入到消息隊列 else { lock (ClassVar.frmMain.lockQue) { ClassVar.frmMain.queue119Xml.Enqueue(conContent); } ClassVar.WriteLogCommon(Environment.NewLine + "收到數據:" + conContent); } } catch (Exception ex) { RemoveUser(user); ClassVar.WriteErrorLog("接收消息異常:" + Environment.NewLine + "ReceiveData" + ex.ToString()); } } } /// <summary>移除用戶</summary> /// <param name="user">指定要刪除的用戶</param> private void RemoveUser(RemoteClient remoteClient) { remoteClientList.Remove(remoteClient); remoteClient.Close(); } }
服務端UI
//服務器給本機發送的心跳計時鎖對象 public object lockQue = new object();
//接收的客戶端消息列表
public Queue<string> queue119Xml = new Queue<string>();
private void IniServer() { //啟動監聽119服務器,用於接收發送119發送的消息 _TcpServer _119TcpListen = new _TcpServer(ClassVar.localIPAddr, 11118); Thread threadRead119 = new Thread(new ThreadStart(Read119QueThread)); threadRead119.IsBackground = true; threadRead119.Start(); } //讀取消息隊列 private void Read119QueThread() { while (true) { try { if (queue119Xml.Count > 0) { lock (lockQue) { string xml = queue119Xml.Dequeue(); F119ToLocal(xml); } } } catch (Exception ex) { ClassVar.WriteErrorLog("方法Read119QueThread出錯,詳細信息:" + ex.ToString()); } Thread.Sleep(5); } }
/// <summary> /// 客戶端類 /// </summary> class _Client { // tcp通信對象 private TcpClient tcpClient; // tcp通信中讀取數據的對象 private BinaryReader br; // tcp通信中寫數據的對象 private BinaryWriter bw; // 通信的遠程服務器ip private string IP; // 通信的遠程服務器端口 private int port; /// <summary> /// 構造函數 /// </summary> /// <param name="ip">服務器IP</param> /// <param name="port">服務器開放的通信端口號</param> public _Client(string ip,int port) { this.IP = ip; this.port = port; } /// <summary> /// 連接服務器 /// </summary> public void Connect() { try { tcpClient = new TcpClient(IP, port); //獲取網絡流 NetworkStream networkStream = tcpClient.GetStream(); //將網絡流作為二進制讀寫對象 br = new BinaryReader(networkStream); bw = new BinaryWriter(networkStream); } catch (Exception ex) { ClassVar.WriteErrorLog("連接服務器出錯:" + Environment.NewLine + "Connect" + ex.ToString()); } //后台心跳消息線程 Thread threadHeart = new Thread(new ThreadStart(SendHeart)); threadHeart.IsBackground = true; threadHeart.Start(); } /// <summary> /// 重連 /// </summary> public void Reconnect() { try { if (tcpClient!=null) { tcpClient.Close(); } tcpClient = new TcpClient(IP, port); //獲取網絡流 NetworkStream networkStream = tcpClient.GetStream(); //將網絡流作為二進制讀寫對象 br = new BinaryReader(networkStream); bw = new BinaryWriter(networkStream); } catch(Exception ex) { ClassVar.WriteErrorLog("重連服務器出錯:" + Environment.NewLine + "Reconnect" + ex.ToString()); } } /// <summary> /// 給服務器心跳,10秒一次 /// </summary> private void SendHeart() { while (true) { Thread.Sleep(10000); SendMsg("0000"); } } /// <summary> /// 發送消息到服務器的方法,帶發送長度 /// </summary> /// <param name="msg">消息內容</param> public void SendMsg(string msgs) { try { byte[] msg = Encoding.UTF8.GetBytes(msgs); int length = msg.Length; short lengthall = (short)(length + 2); byte[] lengthByte = System.BitConverter.GetBytes(lengthall); byte[] all = lengthByte.Concat(msg).ToArray(); //然后將字節數組寫入網絡流 if (bw != null && tcpClient.Connected==true) { bw.Write(all); bw.Flush(); if (msgs == "0000")//心跳寫單獨的文件 { ClassVar.WriteLogCommonXT(Environment.NewLine + "成功發送數據:" + msgs); } else { ClassVar.WriteLogCommon(Environment.NewLine + "成功發送數據:" + msgs); } } else { this.Reconnect(); } } catch (Exception ex) { ClassVar.WriteErrorLog("發送消息到服務器出錯:" + Environment.NewLine + "SendMsg" + ex.ToString()); } } }
客戶端代碼
// 與服務器通信的類 _Client client ; //服務器給本機發送的心跳計時鎖對象 public object objTimeSpan = new object(); //服務器給本機發送的心跳計時 public int timeSpan = 0; private void IniClient() { client = new _Client(_119ServerIP, _119ServerPort); //連接服務器 client.Connect(); //與服務器重連判斷線程 Thread threadChenck = new Thread(new ThreadStart(CheckHeart)); threadChenck.IsBackground = true; threadChenck.Start(); client.SendMsg("測試發送信息到服務端"); } // 重連判斷 private void CheckHeart() { while (true) { Thread.Sleep(3000); lock (objTimeSpan) { timeSpan = timeSpan + 2; } if (timeSpan >= maxTime) { client.Reconnect(); timeSpan = 0; } } }