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

來源:互聯網
上載者:User

來源:中國IT實驗室

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

  一、用戶端數量比較少:

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

  二、用戶端數量較多但都是短串連:

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

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

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

  首先建立一個Socket,並且給它綁定一個EndPoint後開始監聽。接下來我們建立一個線程,在這個線程中我們用一個無限迴圈來接收來自用戶端的串連請求。在接收到一個請求後,為這個用戶端建立一個新的線程,並且在這個線程中也使用一個無限迴圈接收來自這個用戶端的資料。下面讓我們來看看代碼:

  首先我們建立一個Socket用來偵聽用戶端的串連:

Socket listener = new Socket(AddressFamily.InterNetwork, 
SocketType.Stream, ProtocolType.Tcp); IPEndPoint locEP= new IPEndPoint(IPAddress.Any, 2000); listener.Bind(locEP); listener.Listen(100);

  然後建立一個線程來處理用戶端的串連請求:

Thread acceptThread = new Thread(new ThreadStart(AcceptWorkThread));            acceptThread.Start();            private void AcceptWorkThread()            ...{            Thread.CurrentThread.IsBackground = true;            while (true)            ...{            Socket accept = listener.Accept();            IPEndPoint remoEP = (IPEndPoint)accept.RemoteEndPoint;            string recString = "接收到來自" + remoEP.Address.ToString() + "的串連。";            this.Invoke(new AddListItemHandler(this.AddListItem), new string[] ...
{ recString }); Thread receiveThread = new Thread(new ParameterizedThreadStart
(ReceiveWorkThread)); receiveThread.Start(accept); } }

  最後我們來看看如何接收資料:

private void ReceiveWorkThread(object obj)            ...{            Thread.CurrentThread.IsBackground = true;            Socket socket = (Socket)obj;            byte[] buffer = new byte[1024];            while (true)            ...{            int receiveCount = socket.Receive(buffer);            if (receiveCount > 0)            ...{            IPEndPoint remoEP = (IPEndPoint)socket.RemoteEndPoint;            string recString = "來自用戶端" + remoEP.Address.ToString() + "的
訊息:" + Encoding.Default.GetString(buffer, 0, receiveCount); this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); socket.Send(buffer, receiveCount, SocketFlags.None); } else ...{ socket.Close(); break; } } }

  好了,整個實現就完成了。

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

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

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

  首先我們建立一個Socket用來偵聽用戶端的串連:

Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp); IPEndPoint locEP= new IPEndPoint(IPAddress.Any, 2000); listener.Bind(locEP); listener.Listen(100);

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

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

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

private void ClientWorkThread()            ...{            byte[] buffer = new byte[1024];            while (true)            ...{            Socket socket = listener.Accept();            string recString = "接收到來自" + remoEP.Address.ToString() + "的串連。
"; this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); int receCount = socket.Receive(buffer); if (receCount>0) ...{ string recString = "來自用戶端" + remoEP.Address.ToString() + "
的訊息:" + Encoding.Default.GetString(buffer, 0, receiveCount); this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); socket.Send(buffer, receCount, SocketFlags.None); } socket.Shutdown(SocketShutdown.Both); socket.Close(); } }

  為什麼我們要這樣做呢?

  首先我們建立了一個Socket用於偵聽用戶端的串連請求,接下我們建立了一個擁有30個線程的線程池。並在每個線程中實現了Accept、Receive、Send和Close(),以完成串連、接收、發送、關閉的操作。

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.