对.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:以上是个人愚见,废话比较多哈,敬请谅解,因为自己技术水平有限,没法在每一个细节都深刻研究,若有不妥之处,请路过的大神多加指点,小弟在此谢过 ^_^
相关文章
相关标签/搜索