對.Net WebSocket 和Socket的原理的思考

  今早上班路上接到了一個朋友的微信信息,問我對WebSocket 是否熟悉,一楞,印象之中沒有用過這個類....來到公司後,得空問了一下度娘,原來這是一個隨着HTML5推出的一種新協議,意義在於能實現瀏覽器與服務器全雙工通訊(full-duplex)。度娘對此的解釋是:編程

  現不少網站爲了實現即時通信,所用的技術都是輪詢(polling)。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP request,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的HTTP request 的模式帶來很明顯的缺點 – 瀏覽器須要不斷的向服務器發出請求,然而HTTP request 的header是很是長的,裏面包含的有用數據可能只是一個很小的值,這樣會佔用不少的帶寬。
  而比較新的技術去作輪詢的效果是Comet – 用了AJAX。但這種技術雖然可達到全雙工通訊,但依然須要發出請求。
在 WebSocket API,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。在此WebSocket 協議中,爲咱們實現即時服務帶來了兩大好處:
  1. Header
    互相溝通的Header是很小的-大概只有 2 Bytes
  2. Server Push
 
  如上解釋,WebSocket 是一個很是不錯的東東,然而,我那個朋友正須要使用客戶端對服務端作輪詢查詢,按照經常使用的解決方案,經過在客戶端輪詢地向服務端發起Http請求,或者經過Socket直接創建長鏈接獲取最新的數據,而後更新呈現的內容即可以完成任務,不過那好學的朋友可能以爲WebSocket 新鮮吧,不斷追問WebSocket 和剛纔兩個解決方案哪一個更好,WebSocket 和Socket區別在哪裏?它們的底層原理是否同樣?因爲本身也從未用過WebSocket ,也不知和soket的區別在哪,那麼問題來了,網上搜了一下,關於這個問題的解答真是少之又少,而後去看了下 .NET Core的開源源碼,在System.Net.WebSockets的WinHttpWebSocket類和System.Net.Sockets的 Socket類當中發現了一點線索,也許能解答這個問題。
internal class WinHttpWebSocket : WebSocket
{
    .....
public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)   {    .....     _operation.SessionHandle = InitializeWinHttp(options);     _operation.ConnectionHandle = Interop.WinHttp.WinHttpConnectWithCallback( _operation.SessionHandle, uri.IdnHost, (ushort)uri.Port, 0);     ThrowOnInvalidHandle(_operation.ConnectionHandle); bool secureConnection = uri.Scheme == UriScheme.Https || uri.Scheme == UriScheme.Wss; _operation.RequestHandle = Interop.WinHttp.WinHttpOpenRequestWithCallback( _operation.ConnectionHandle, "GET", uri.PathAndQuery, null, Interop.WinHttp.WINHTTP_NO_REFERER, null, secureConnection ? Interop.WinHttp.WINHTTP_FLAG_SECURE : 0); ThrowOnInvalidHandle(_operation.RequestHandle); _operation.IncrementHandlesOpenWithCallback();   .....   }  ...... }

  

namespace System.Net.Sockets
{
  public partial class Socket : IDisposable
  {
     .......

     public void Connect(EndPoint remoteEP)
    {
      ......
      
          EndPoint endPointSnapshot = remoteEP;
          Internals.SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
          if (!Blocking)
          {
              _nonBlockingConnectRightEndPoint = endPointSnapshot;
              _nonBlockingConnectInProgress = true;
          }

          DoConnect(endPointSnapshot, socketAddress);
    }
     private void DoConnect(EndPoint endPointSnapshot, Internals.SocketAddress socketAddress)
     {
      .......

      SocketError errorCode = SocketPal.Connect(_handle, socketAddress.Buffer, socketAddress.Size);

      ......
     }

     ......
  }
}
namespace System.Net.Sockets {  internal static class SocketPal   {     .......     public static SocketError Connect(SafeCloseSocket handle, byte[] peerAddress, int peerAddressLen) { SocketError errorCode = Interop.Winsock.WSAConnect( handle.DangerousGetHandle(), peerAddress, peerAddressLen, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success; }     .......   } }

  

由上面代碼可見,windows

(1)WebSocket最終調用了WinHTTP 的api,WinHTTP的全稱是Microsoft Windows HTTP Services, 它提供給開發者一個HTTP客戶端應用程序接口(API), 經過這種API藉助HTTP協議給其餘的HTTP服務器發送請求.關於WinHTTP 的詳細API,請自行查詢資料,網上一大把,這裏再也不累贅copy。由此能夠驗證了WebSocket是基於HTTP請求的,從調用的WinHTTPAPI方法名稱能夠得知,都是帶有回調的方法,也正驗證了WebSocket的雙工通訊的特色。api

(2)Socket最終是調用了windows的Winsock接口,Winsock是Windows下的網絡編程接口,它是由Unix下的BSD Socket發展而來,是一個與網絡協議無關的編程接口。具體信息請自行查詢網上資源。瀏覽器

所以,我我的以爲,WebSocket和Socket在技術上並無太多關係,底層原理也是不一樣的,WebSocket 是爲了知足基於 Web 的日益增加的實時通訊需求而產生的,能夠在一些實時通訊時,代替採用 HTTP 協議不斷髮送請求的通用的方式,以達到帶寬浪費和服務器 CPU 的消耗,更重要的是它是一種協議,而Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口,並非協議,WebSocket不能等同Socket,也不是Socket的演化,更不能代替Socket。服務器

ps:以上是個人愚見,廢話比較多哈,敬請諒解,因爲自己技術水平有限,沒法在每一個細節都深刻研究,若有不妥之處,請路過的大神多加指點,小弟在此謝過 ^_^
相關文章
相關標籤/搜索