HTML5 WebSocket与C# 建立Socket连接

时间:2023-03-09 19:04:51
HTML5 WebSocket与C# 建立Socket连接

一、WebSocket

1、概述

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

HTML5 WebSocket与C# 建立Socket连接

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

2、WebSocket 属性

  1. Socket.readyState:    只读属性 readyState 表示连接状态,可以是以下值:
  • 0 - 表示连接尚未建立。
  • 1 - 表示连接已建立,可以进行通信。
  • 2 - 表示连接正在进行关闭。
  • 3 - 表示连接已经关闭或者连接不能打开。
  • Socket.bufferedAmount:    只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
  • 3、WebSocket 事件

    • open :   Socket.onopen    连接建立时触发
    • message :   Socket.onmessage    客户端接收服务端数据时触发
    • error :   Socket.onerror    通信发生错误时触发
    • close :   Socket.onclose    连接关闭时触发

    4、WebSocket 方法

    • Socket.send() :   使用连接发送数据
    • Socket.close():    关闭连接

    5、Websocket握手请求

    WebSocket 协议本质上是一个基于 TCP 的协议。

    为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道*的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

    客户端请求

    GET / HTTP/1.1
    Upgrade: websocket
    Connection: Upgrade
    Host: example.com
    Origin: http://example.com
    Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
    Sec-WebSocket-Version: 13

    服务器回应

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
    Sec-WebSocket-Location: ws://example.com/
    • Connection 必须设置 Upgrade,表示客户端希望连接升级。
    • Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。
    • Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。

    6、Websocket 端口

    Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:

    ws://example.com/wsapi
    wss://secure.example.com/

    Websocket 使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口。

    7、客户端代码

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title> <script type="text/javascript">
    function WebSocketTest()
    {
    if ("WebSocket" in window)
    {
    alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket
    var ws = new WebSocket("ws://localhost:9998/echo"); ws.onopen = function()
    {
    // Web Socket 已连接上,使用 send() 方法发送数据
    ws.send("发送数据");
    alert("数据发送中...");
    }; ws.onmessage = function (evt)
    {
    var received_msg = evt.data;
    alert("数据已接收...");
    }; ws.onclose = function()
    {
    // 关闭 websocket
    alert("连接已关闭...");
    };
    } else
    {
    // 浏览器不支持 WebSocket
    alert("您的浏览器不支持 WebSocket!");
    }
    }
    </script> </head>
    <body> <div id="sse">
    <a href="javascript:WebSocketTest()">运行 WebSocket</a>
    </div> </body>
    </html>

    二、C# 建立Socket连接

    1、利用原始socket

    https://www.cnblogs.com/xqaizx/p/9446863.html

    2、利用第三方库

    c#可以选择websocket-sharp来实现websocket Server。或者https://github.com/Azure/DotNetty

    class Program
    {
    static void Main(string[] args)
    {
    var wssv = new WebSocketServer(10086);
    wssv.AddWebSocketService<ScannerHandler>("/scan");
    wssv.Start();
    if (wssv.IsListening)
    {
    Console.WriteLine("Listening on port {0}, and providing WebSocket services:", wssv.Port);
    foreach (var path in wssv.WebSocketServices.Paths)
    Console.WriteLine("- {0}", path);
    } Console.WriteLine("\nPress Enter key to stop the server...");
    Console.ReadLine(); wssv.Stop();
    }
    } public class ScannerHandler : WebSocketBehavior
    {
    protected override void OnMessage(MessageEventArgs e)
    {
    if(e.Data == "scan")
    {
    ScanResult result = ScanerHelper.Scan("D:\\test.jpg");
    if (result.Success)
    {
    Console.WriteLine("scan success");
    Send("scan success");
    }
    else
    {
    Send("scan eror");
    }
    } }
    }