創建一個socket服務類,綁定監聽端口,
然后創建一個線程listen連接的客戶端,
把監聽到的客戶端加入dictionary里面,以便於管理,
同時創建receive線程,循環接收數據加入list緩存區,解決粘包或者分包的情況,
關閉服務時,需要將連接上的socket逐個shutdown。
/* * * 該類用於管理tcp連接通訊 * */ using System; using System.Collections.Generic; using System.Net.Sockets; using System.Threading; using System.Net; namespace Communication { /// <summary> /// 服務端 /// </summary> public class MyTcpServer { private Socket ServerSocket = null;//服務端 public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客戶端字典 private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//線程字典,每新增一個連接就添加一條線程 private bool Flag_Listen = true;//監聽客戶端連接的標志 /// <summary> /// 啟動服務 /// </summary> /// <param name="port">端口號</param> public bool OpenServer(int port) { try { Flag_Listen = true; // 創建負責監聽的套接字,注意其中的參數; ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 創建包含ip和端口號的網絡節點對象; IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port); try { // 將負責監聽的套接字綁定到唯一的ip和端口上; ServerSocket.Bind(endPoint); } catch { return false; } // 設置監聽隊列的長度; ServerSocket.Listen(100); // 創建負責監聽的線程; Thread Thread_ServerListen = new Thread(ListenConnecting); Thread_ServerListen.IsBackground = true; Thread_ServerListen.Start(); return true; } catch { return false; } } /// <summary> /// 關閉服務 /// </summary> public void CloseServer() { lock (dic_ClientSocket) { foreach (var item in dic_ClientSocket) { item.Value.Close();//關閉每一個連接 } dic_ClientSocket.Clear();//清除字典 } lock (dic_ClientThread) { foreach (var item in dic_ClientThread) { item.Value.Abort();//停止線程 } dic_ClientThread.Clear(); } Flag_Listen = false; //ServerSocket.Shutdown(SocketShutdown.Both);//服務端不能主動關閉連接,需要把監聽到的連接逐個關閉 if (ServerSocket != null) ServerSocket.Close(); } /// <summary> /// 監聽客戶端請求的方法; /// </summary> private void ListenConnecting() { while (Flag_Listen) // 持續不斷的監聽客戶端的連接請求; { try { Socket sokConnection = ServerSocket.Accept(); // 一旦監聽到一個客戶端的請求,就返回一個與該客戶端通信的 套接字; // 將與客戶端連接的 套接字 對象添加到集合中; string str_EndPoint = sokConnection.RemoteEndPoint.ToString(); MySession myTcpClient = new MySession() { TcpSocket = sokConnection }; //創建線程接收數據 Thread th_ReceiveData = new Thread(ReceiveData); th_ReceiveData.IsBackground = true; th_ReceiveData.Start(myTcpClient); //把線程及客戶連接加入字典 dic_ClientThread.Add(str_EndPoint, th_ReceiveData); dic_ClientSocket.Add(str_EndPoint, myTcpClient); } catch { } Thread.Sleep(200); } } /// <summary> /// 接收數據 /// </summary> /// <param name="sokConnectionparn"></param> private void ReceiveData(object sokConnectionparn) { MySession tcpClient = sokConnectionparn as MySession; Socket socketClient = tcpClient.TcpSocket; bool Flag_Receive = true; while (Flag_Receive) { try { // 定義一個2M的緩存區; byte[] arrMsgRec = new byte[1024 * 1024 * 2]; // 將接受到的數據存入到輸入 arrMsgRec中; int length = -1; try { length = socketClient.Receive(arrMsgRec); // 接收數據,並返回數據的長度; } catch { Flag_Receive = false; // 從通信線程集合中刪除被中斷連接的通信線程對象; string keystr = socketClient.RemoteEndPoint.ToString(); dic_ClientSocket.Remove(keystr);//刪除客戶端字典中該socket dic_ClientThread[keystr].Abort();//關閉線程 dic_ClientThread.Remove(keystr);//刪除字典中該線程 tcpClient = null; socketClient = null; break; } byte[] buf = new byte[length]; Array.Copy(arrMsgRec, buf, length); lock (tcpClient.m_Buffer) { tcpClient.AddQueue(buf); } } catch { } Thread.Sleep(100); } } /// <summary> /// 發送數據給指定的客戶端 /// </summary> /// <param name="_endPoint">客戶端套接字</param> /// <param name="_buf">發送的數組</param> /// <returns></returns> public bool SendData(string _endPoint, byte[] _buf) { MySession myT = new MySession(); if (dic_ClientSocket.TryGetValue(_endPoint, out myT)) { myT.Send(_buf); return true; } else { return false; } } } /// <summary> /// 會話端 /// </summary> public class MySession { public Socket TcpSocket;//socket對象 public List<byte> m_Buffer = new List<byte>();//數據緩存區 public MySession() { } /// <summary> /// 發送數據 /// </summary> /// <param name="buf"></param> public void Send(byte[] buf) { if (buf != null) { TcpSocket.Send(buf); } } /// <summary> /// 獲取連接的ip /// </summary> /// <returns></returns> public string GetIp() { IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint; string _ip = clientipe.Address.ToString(); return _ip; } /// <summary> /// 關閉連接 /// </summary> public void Close() { TcpSocket.Shutdown(SocketShutdown.Both); } /// <summary> /// 提取正確數據包 /// </summary> public byte[] GetBuffer(int startIndex, int size) { byte[] buf = new byte[size]; m_Buffer.CopyTo(startIndex, buf, 0, size); m_Buffer.RemoveRange(0, startIndex + size); return buf; } /// <summary> /// 添加隊列數據 /// </summary> /// <param name="buffer"></param> public void AddQueue(byte[] buffer) { m_Buffer.AddRange(buffer); } /// <summary> /// 清除緩存 /// </summary> public void ClearQueue() { m_Buffer.Clear(); } } }
the end