国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

閑來無事,寫個基于TCP協議的Socket通訊Demo

2019-11-17 03:19:55
字體:
來源:轉載
供稿:網友

閑來無事,寫個基于TCP協議的Socket通訊Demo

  .Net Socket通訊可以使用Socket類,也可以使用 TcpClient、 TcpListener 和 UdpClient類。我這里使用的是Socket類,Tcp協議。

  程序很簡單,一個命令行的服務端,一個命令行的客戶端。服務端啟動后根據輸入的端口號綁定本機端口并啟動偵聽,客戶端啟動后根據輸入的客戶端數量、服務ip、服務端口號連接服務端。客戶端連接成功后啟動新線程隨機發送消息到服務端并等待接收服務端返回的消息,服務端和客戶端成功創建連接后啟動新線程接收客戶端消息并返回客戶端一個消息,如此循環下去……

  上圖:

圖1. 客戶端運行界面

圖2. 服務端運行界面

圖3. 項目結構

  

  

服務端關鍵代碼

  啟動偵聽:

1 var endPoint = new IPEndPoint(0, port);2 var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, PRotocolType.Tcp);3 socket.Bind(endPoint);4 socket.Listen(int.MaxValue);

  啟動新線程接收客戶端連接:

1 // 啟動新線程負責接受客戶端連接2 var socketThread = new Thread(OnSocketAccept) {IsBackground = true};3 socketThread.Start(socket);4 Show("服務準備就緒");

  接收客戶端連接細節:

 1 /// <summary> 2 /// 建立Socket連接 3 /// </summary> 4 /// <param name="obj"></param> 5 private static void OnSocketAccept(object obj) 6 { 7     try 8     { 9         var socket = obj as Socket;10         while (true)11         {12             try13             {14                 Socket clientSocket = socket.Accept();15                 ...16                 // 嘗試獲取鎖,超時則關閉當前連接并繼續下次循環17                 if (!Monitor.TryEnter(ClientDictLock, LockTimeOut))18                 {19                     CloseSocket(socket, key);20                     continue;   21                 }22                 try23                 {24                     // 當然連接已存在則先關閉再緩存新連接25                     if (ClientDict.ContainsKey(key))26                     {27                         CloseSocket(ClientDict[key], key);28                         ClientDict[key] = clientSocket;29                     }30                     else31                     {32                         ClientDict.Add(key, clientSocket);33                     }34                 }35                 finally36                 {37                     Monitor.Exit(ClientDictLock);38                 }39                 // 啟動線程池線程執行接收和發送操作40                 ThreadPool.QueueUserWorkItem(OnSendOrReceive, clientSocket);41             }42             catch (ThreadAbortException)43             {44                 throw;45             }46             catch (Exception exception)47             {48                 ...49             }50         }51     }52     catch (ThreadAbortException)53     {54         ...55     }56     catch (Exception exception)57     {58         ...59     }60 }

  發送/接收數據:

 1 /// <summary> 2 /// 接收/發送數據 3 /// </summary> 4 /// <param name="obj"></param> 5 private static void OnSendOrReceive(object obj) 6 { 7     try 8     { 9         var socket = obj as Socket;10         ...11         while (true)12         {13             try14             {15                 ...16                 // 接收數據17                 var receiveLength = socket.Receive(receiveBuffer);18                 ...19                 // 發送數據20                 var sendLength = socket.Send(sendBuffer);21                 ...22             }23             catch (ThreadAbortException)24             {25                 throw;26             }27             catch (SocketException exception)28             {29                 CloseSocket(socket, key);30                 break;31             }32             catch (Exception exception)33             {34                 ...35             }36         }37     }38     catch (ThreadAbortException)39     {40     }41     catch (Exception exception)42     {43         ...44     }45 }

  關閉連接:

 1 /// <summary> 2 /// 關閉連接 3 /// </summary> 4 /// <param name="socket"></param> 5 /// <param name="key"></param> 6 private static void CloseSocket(Socket socket, IPEndPoint key) 7 { 8     socket.Shutdown(SocketShutdown.Both); 9     socket.Disconnect(true);10     socket.Close();11     socket.Dispose();12     ...13 }

客戶端關鍵代碼

  連接服務端:

// 根據客戶端數量建立Socket連接for (int i = 1; i <= clientNum; i++){    ConnetServer(address, port, i);}/// <summary>/// 建立Socket連接/// </summary>/// <param name="address"></param>/// <param name="port"></param>/// <param name="id"></param>static void ConnetServer(IPAddress address, int port, int id){    try    {        var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        // 連接服務端        clientSocket.Connect(address, port);        ...                // 啟動線程池線程開始發送數據和接收數據        ThreadPool.QueueUserWorkItem(OnSendOrReceive, clientSocket);    }    catch (Exception exception)    {        ...    }}

  發送/接收數據、關閉連接代碼同服務端一樣。

  優先使用線程池線程,服務端接受客戶端連接使用獨立線程(socketThread)是考慮到可能需要手工停止該線程。

  使用 Monitor.TryEnter(ClientDictLock, LockTimeOut) 和 Monitor.Exit(ClientDictLock); 是考慮到 lock 可能形成死鎖,使用lock需要注意。

  本人才疏學淺,歡迎大家批評指正!

源代碼下載

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 博兴县| 鄂托克前旗| 会泽县| 桐柏县| 湟中县| 承德市| 宁河县| 酉阳| 水富县| 夹江县| 普安县| 大田县| 略阳县| 永安市| 新干县| 三穗县| 汨罗市| 洪雅县| 成都市| 格尔木市| 新民市| 四川省| 靖安县| 金门县| 扎鲁特旗| 临江市| 曲麻莱县| 崇州市| 安塞县| 嘉禾县| 水富县| 扎囊县| 大英县| 安陆市| 富裕县| 潞西市| 交口县| 子洲县| 华亭县| 札达县| 民权县|