熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

.NET Socket開發之同步Socket實現兩例

2022-06-13   來源: .NET編程 

  今天我們來講一下在NET 網絡應用程序開發中同步Socket的應用很多人認為在網絡應用的服務端Socket不應該使用同步Socket是的在大多數情況下是這樣的但是也有一些場景下我們使用同步Socket可能會得到更的結果如在下面的兩種場景下我們便可以考慮使用同步的Socket

  一客戶端數量比較少

  數量比較少是指會同時連接到服務器的客戶端數量一般在人以下這種情況下我們可以考慮使用同步Socket+Thread來實現我們的服務端這樣會讓我們編寫邏輯更清晰的代碼而性能不會下降太多

  二客戶端數量較多但都是短連接

  短連接是指客戶端的連接在處理完一次收發之後就產即斷開的場景比如說HTTP協議就是一種短連接HTTP在客戶端發出請求時建立一個Socket連接並通過Socket發出一個URL請求服務端在處理完這個請求並回發相應的頁面後便會斷開這個連接那麼在這種場景下我們也可以使用同步Socket來實現我們的需求

  那麼應該如果實現我上面提到的兩種需求呢對於這兩種需求我將采用不同的方案來實現它們

  首先我們來看看第一種需求這裡我采用Socket+Thread來實現基本的流程如下

  首先創建一個Socket並且給它綁定一個EndPoint後開始監聽接下來我們創建一個線程在這個線程中我們用一個無限循環來接收來自客戶端的連接請求在接收到一個請求後為這個客戶端創建一個新的線程並且在這個線程中也使用一個無限循環接收來自這個客戶端的數據下面讓我們來看看代碼

  首先我們創建一個Socket用來偵聽客戶端的連接

  

  Socket listener = new Socket(AddressFamilyInterNetwork
SocketTypeStream ProtocolTypeTcp); IPEndPoint locEP= new IPEndPoint(IPAddressAny ); listenerBind(locEP); listenerListen();

  然後創建一個線程來處理客戶端的連接請求

  

  Thread acceptThread = new Thread(new ThreadStart(AcceptWorkThread)); acceptThreadStart(); private void AcceptWorkThread() { ThreadCurrentThreadIsBackground = true; while (true) { Socket accept = listenerAccept(); IPEndPoint remoEP = (IPEndPoint)acceptRemoteEndPoint; string recString = 接收到來自 + remoEPAddressToString() + 的連接; thisInvoke(new AddListItemHandler(thisAddListItem) new string[]
{ recString }); Thread receiveThread = new Thread(new ParameterizedThreadStart
(ReceiveWorkThread)); receiveThreadStart(accept); } }

  最後我們來看看如何接收數據

  

  private void ReceiveWorkThread(object obj) { ThreadCurrentThreadIsBackground = true; Socket socket = (Socket)obj; byte[] buffer = new byte[]; while (true) { int receiveCount = socketReceive(buffer); if (receiveCount > ) { IPEndPoint remoEP = (IPEndPoint)socketRemoteEndPoint; string recString = 來自客戶端 + remoEPAddressToString() +
消息 + EncodingDefaultGetString(buffer receiveCount); thisInvoke(new AddListItemHandler(thisAddListItem) new string[]
{ recString }); socketSend(buffer receiveCount SocketFlagsNone); } else { socketClose(); break; } } }

  好了整個實現就完成了

  現在讓我們來看看第二個需求

  這個方案我們將采用另外一個方法來實現為什麼不采用上一個方法來實現呢?讓我們來分析一下我們知道在上一個實現中每接入一個客戶端就要創建一個線程如果有大量的客戶端接入的話就會創建過多的線程但是如果線程過多的話Windows就需要更多的CPU時間來切換線程的上下文(這也是上一個實現不能接入很多客戶端的原因)

  我們知道在這個方案中每一個連接都是短連接而且順序都是固定的都是接入>接收>發送這樣的順序那麼我們就可以在一個方法中完成整個處理這樣我們就可以利用線程池來實現我們所需要的好了讓我們用代碼來說話吧

  首先我們創建一個Socket用來偵聽客戶端的連接

  

  Socket listener = new Socket(AddressFamilyInterNetwork SocketTypeStream
ProtocolTypeTcp); IPEndPoint locEP= new IPEndPoint(IPAddressAny ); listenerBind(locEP); listenerListen();

  接下來我們要創建一個線程池

  

  Thread[] ClientThreadList = new Thread[]; foreach (Thread th in ClientThreadList) { th = new Thread(new ThreadStart(ClientWorkThread)); thStart(); }

  最後讓我們看看線程都要做些什麼

  

  private void ClientWorkThread() { byte[] buffer = new byte[]; while (true) { Socket socket = listenerAccept(); string recString = 接收到來自 + remoEPAddressToString() + 的連接
; thisInvoke(new AddListItemHandler(thisAddListItem) new string[]
{ recString }); int receCount = socketReceive(buffer); if (receCount>) { string recString = 來自客戶端 + remoEPAddressToString() +
的消息 + EncodingDefaultGetString(buffer receiveCount); thisInvoke(new AddListItemHandler(thisAddListItem) new string[]
{ recString }); socketSend(buffer receCount SocketFlagsNone); } socketShutdown(SocketShutdownBoth); socketClose(); } }

  為什麼我們要這樣做呢?

  首先我們創建了一個Socket用於偵聽客戶端的連接請求接下我們創建了一個擁有個線程的線程池並在每個線程中實現了AcceptReceiveSend和Close()以完成連接接收發送關閉的操作

  現在我們假設有一個客戶連接到服務器了這時會有一個線程Accept到這個請求並開始接收客戶端發送過來的數據接收到數據之後處理完發送給客戶端然後關閉這個連接再次進入等待連接狀態而其它個線程由於沒有Accept到這個請求仍然處理等待接入狀態


From:http://tw.wingwit.com/Article/program/net/201311/13321.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.