郎头疼 發表於 2019-7-1 10:39:00

HTML5(12) 实时通讯WebSocket

<h2>一、WebSocket</h2>
<h3>1、概述</h3>
<p>WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行<span style="background-color: rgba(255, 255, 0, 1)">全双工通讯</span>的协议。</p>
<p>WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。</p>
<p>HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。</p>
<p><img src="https://www.runoob.com/wp-content/uploads/2016/03/ws.png"></p>
<p>浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。</p>
<p>以下 API 用于创建 WebSocket 对象。</p>
<div class="cnblogs_code" style="padding: 5px; border: 1px solid rgba(204, 204, 204, 1); background-color: rgba(245, 245, 245, 1); border-image: none">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> Socket = <span style="color: rgba(0, 0, 255, 1)">new</span> WebSocket(url, );</pre>
</div>
<p>以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。</p>
<h3>2、WebSocket 属性</h3>
<ol>
<li>Socket.readyState:&nbsp;&nbsp;&nbsp; 只读属性 readyState 表示连接状态,可以是以下值:</li>
<ul>
<li>0 - 表示连接尚未建立。</li>
<li>1 - 表示连接已建立,可以进行通信。</li>
<li>2 - 表示连接正在进行关闭。</li>
<li>3 - 表示连接已经关闭或者连接不能打开。</li>
</ul>
<li>Socket.bufferedAmount:&nbsp;&nbsp;&nbsp; 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。</li>
</ol>
<h3>3、WebSocket 事件</h3>
<ul>
<li>open :&nbsp;&nbsp; Socket.onopen&nbsp;&nbsp;&nbsp; 连接建立时触发</li>
<li>message :&nbsp;&nbsp; Socket.onmessage&nbsp;&nbsp;&nbsp; 客户端接收服务端数据时触发</li>
<li>error :&nbsp;&nbsp; Socket.onerror&nbsp;&nbsp;&nbsp; 通信发生错误时触发</li>
<li>close :&nbsp;&nbsp; Socket.onclose&nbsp;&nbsp;&nbsp; 连接关闭时触发</li>
</ul>
<h3>4、WebSocket 方法</h3>
<ul>
<li>Socket.send() :&nbsp;&nbsp; 使用连接发送数据</li>
<li>Socket.close():&nbsp;&nbsp;&nbsp; 关闭连接</li>
</ul>
<h3>5、Websocket握手请求</h3>
<p>WebSocket 协议本质上是一个基于 TCP 的协议。</p>
<p>为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。</p>
<p><strong>客户端请求</strong></p>
<blockquote>
<pre>GET / HTTP/1.1
<span style="background-color: rgba(255, 255, 0, 1)">Upgrade: websocket</span><span style="background-color: rgba(255, 255, 0, 1)">
Connection: Upgrade</span>
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13</pre>
</blockquote>
<p><strong>服务器回应</strong></p>
<blockquote>
<pre>HTTP/1.1 101 Switching Protocols
<span style="background-color: rgba(255, 255, 0, 1)">Upgrade: websocket
Connection: Upgrade</span>
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/</pre>
</blockquote>
<ul>
<li>Connection 必须设置 Upgrade,表示客户端希望连接升级。</li>
<li>Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。</li>
<li>Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。</li>
</ul>
<h3>6、Websocket 端口</h3>
<p>Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:</p>
<blockquote>
<pre><span style="background-color: rgba(255, 255, 0, 1)">ws://</span>example.com/wsapi
<span style="background-color: rgba(255, 255, 0, 1)">wss://</span>secure.example.com/</pre>
</blockquote>
<p>Websocket 使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口。</p>
<h3>7、客户端代码</h3>
<div class="cnblogs_code" style="padding: 5px; border: 1px solid rgba(204, 204, 204, 1); background-color: rgba(245, 245, 245, 1); border-image: none">
<pre>菜鸟教程(runoob.com)

</pre>
<div id="sse">运行 WebSocket</div>
</div>
<h2>二、C# 建立Socket连接</h2>
<h3>1、利用原始socket</h3>
<p>https://www.cnblogs.com/xqaizx/p/9446863.html</p>
<h3>2、利用第三方库</h3>
<p>c#可以选择websocket-sharp来实现websocket Server。或者https://github.com/Azure/DotNetty</p>
<div class="cnblogs_code" style="padding: 5px; border: 1px solid rgba(204, 204, 204, 1); background-color: rgba(245, 245, 245, 1); border-image: none">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
    {
      </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> wssv = <span style="color: rgba(0, 0, 255, 1)">new</span> WebSocketServer(<span style="color: rgba(128, 0, 128, 1)">10086</span><span style="color: rgba(0, 0, 0, 1)">);
            wssv.AddWebSocketService</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/scan</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            wssv.Start();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (wssv.IsListening)
            {
                Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Listening on port {0}, and providing WebSocket services:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, wssv.Port);
                </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> path <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> wssv.WebSocketServices.Paths)
                  Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">- {0}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, path);
            }

            Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\nPress Enter key to stop the server...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            Console.ReadLine();

            wssv.Stop();
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ScannerHandler : WebSocketBehavior
    {
      </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> OnMessage(MessageEventArgs e)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(e.Data == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">scan</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                ScanResult result </span>= ScanerHelper.Scan(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">D:\\test.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (result.Success)
                {
                  Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">scan success</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                  Send(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">scan success</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                }
                </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
                {
                  Send(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">scan eror</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                }
            }
         
      }
    }</span></pre>
</div><br><br>
来源:https://www.cnblogs.com/springsnow/p/11112765.html
頁: [1]
查看完整版本: HTML5(12) 实时通讯WebSocket