IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> C#实现WebSocket服务器:(01)握手 -> 正文阅读

[网络协议]C#实现WebSocket服务器:(01)握手

WebSocket的握手是基于HTTP的,所以我们所有的后续文章,还是基于我们前面的HTTP服务器。
项目托管地址:https://github.com/hooow-does-it-work/http

0、判断一个HTTP请求为WebSocket握手请求

HTTP请求的Connection标头值为Upgrade,Upgrade标头的值为websocket,即表示当前请求为WebSocket握手请求。
我们在HttpRequest类中增加如下属性来判断。

/// <summary>
/// 判断请求是不是WebSocket请求
/// </summary>
public bool IsWebSocket
{
    get
    {
        string connection = _headers["connection"];
        string upgrade = _headers["Upgrade"];
        return !string.IsNullOrEmpty(connection) 
            && connection.ToLower() == "upgrade" 
            && !string.IsNullOrEmpty(upgrade) 
            && upgrade.ToLower() == "websocket";
    }
}

1、握手

HttpServerBase类的NewClient重载中增加WebSocket握手请求的判断。

 //捕获一个HttpRequest
request = HttpRequest.Capture(stream);

///如果是WebSocket,调用相应的处理方法
if (request.IsWebSocket)
{
    if(!OnWebSocketInternal(request, stream))
    {
        //WebSocket处理异常,关闭基础流
        stream.Close();
    }
    return;
}

发现是WebSocket请求后,交给OnWebSocketInternal方法处理。
读取客户端发送的Sec-WebSocket-Key标头,拼接上WebSocket协议固定的一个Salt值:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
然后对拼接好的值使用SHA1算法计算摘要,对摘要进行Base64编码后,作为响应给客户端的Sec-WebSocket-Accept标头值。

SHA1计算的摘要大小为20字节,Base64编码后,变为28字节,所以Sec-WebSocket-Accept值的长度是28。

private bool OnWebSocketInternal(HttpRequest request, Stream stream)
{
    string webSocketKey = request.Headers["Sec-WebSocket-Key"];
    if(string.IsNullOrEmpty(webSocketKey))
    {
        OnBadRequest(stream, "header 'Sec-WebSocket-Key' error");
        return false;
    }

    //获取客户端发送来的Sec-WebSocket-Key字节数组
    byte[] keyBytes = Encoding.ASCII.GetBytes(webSocketKey);

    //拼接上WebSocket的Salt,固定值:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
    keyBytes = keyBytes.Concat(ProtocolUtils.Salt).ToArray();

    //计算HASH值,作为响应给客户端的Sec-WebSocket-Accept
    string secWebSocketAcceptKey = ProtocolUtils.SHA1(keyBytes);

    //响应101状态码给客户端
    HttpResponser responser = new HttpResponser(101);
    responser["Upgrade"] = "websocket";
    responser["Connection"] = "Upgrade";

    //设置Sec-WebSocket-Accept头
    responser["Sec-WebSocket-Accept"] = secWebSocketAcceptKey;

    //发送响应
    responser.WriteHeader(stream);

    //开始WebSocket消息的接收和发送
    OnWebSocket(request, stream);
    return true;
}

至此,握手完成,后续消息的读取和写入,交给OnWebSocket来处理,OnWebSocket为虚方法,可以在子类实现相应的逻辑。
基类的OnWebSocket方法,只是单纯的关闭了基础流。

2、握手测试

实现一个服务器。
把文件https://github.com/hooow-does-it-work/http/blob/main/bin/Release/web/websocket.html放在WebRoot目录,作为WebSocket的测试页。

public class HttpServer : HttpServerBase
{
    public HttpServer() : base()
    {
        //设置根目录
        WebRoot = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web"));
    }
    protected override void OnWebSocket(HttpRequest request, Stream stream)
    {
        base.OnWebSocket(request, stream);
    }
}

运行服务器,浏览器访问:http://127.0.0.1:4189/websocket.html
在这里插入图片描述
可以看到,服务端响应了101状态和正确的Sec-WebSocket-Accept标头,WebSocket握手成功。
客户端发送了一条消息,因为我们默认服务端的OnWebSocket没有实现消息的读写,只是关闭了基础流,所以页面显示,连接成功后立即被关闭了。

3、总结

1、三个重要的请求标头:Connection、Upgrade、Sec-WebSocket-Key
2、三个重要的响应标头:Connection、Upgrade、Sec-WebSocket-Accept
3、Sec-WebSocket-Accept值的生成和101状态码。

后面文章进行WebSocket消息的解析。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 11:12:15  更:2021-09-10 11:12:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年6日历 -2024/6/18 19:10:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码