区分 TcpClient 和 WebSocket?

Posted

技术标签:

【中文标题】区分 TcpClient 和 WebSocket?【英文标题】:Differentiate between TcpClient and WebSocket? 【发布时间】:2014-09-25 07:28:59 【问题描述】:

我正在开发一个应用程序,其中我使用套接字在服务器应用程序和客户端应用程序(Web 和桌面两者)之间进行通信。 我的服务器应用程序不断监听客户端应用程序的请求并在任何时候接受请求. 服务器代码:

TcpListener listener = new TcpListener(IPAddress.Parse(ipAddStr), portNum);
listener.Start();
while (listen)

    TcpClient handler = listener.AcceptTcpClient();
    // doing some stuff
    // for every client handler i am creating a new thread and start listening for the next request

对于 Web 客户端,我使用的是 WebSocket,至于与 WebSocket 客户端建立连接,我们必须遵循一些握手过程。为此,我正在使用以下代码(工作正常):

    static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    private static string AcceptKey(ref string key)
    
        string longKey = key + guid;
        SHA1 sha1 = SHA1CryptoServiceProvider.Create();
        byte[] hashBytes = sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(longKey));
        return Convert.ToBase64String(hashBytes);
    

为与 websocket 客户端握手生成和发送响应:

       // generate accept key fromm client header request
        var key = headerRequest.Replace("ey:", "`")
                         .Split('`')[1]                     
                         .Replace("\r", "").Split('\n')[0]  
                         .Trim();
        var responseKey = AcceptKey(ref key);

        //create the response for the webclient
        var newLine = "\r\n";
        var response = "HTTP/1.1 101 Switching Protocols" + newLine
                     + "Upgrade: websocket" + newLine
                     + "Connection: Upgrade" + newLine
                     + "Sec-WebSocket-Accept: " + responseKey + newLine + newLine;

        //send respose to the webclient
        Byte[] sendBytes = Encoding.ASCII.GetBytes(response);
        networkStream.Write(sendBytes, 0, sendBytes.Length);
        networkStream.Flush();

我也有TcpClient 用于桌面应用程序的套接字,所以问题是如何识别请求来自WebSocket 还是来自TcpClient

【问题讨论】:

【参考方案1】:

最简单的方法是让 websocket 侦听器和 vanilla TCP 侦听器侦听不同的端口号。无论如何,您都应该这样做,因为 websocket 应用程序通常在标准 http 端口 80(或标准 https 端口 443 当您使用带有 TLS 的 websockets 时)上运行,而基于 TCP 的自定义协议应该在一个上运行“注册”范围内的端口中的 1024 到 49151 之间的端口。建议您遵循这一点,因为一个安全的客户端环境允许 Web 访问但没有太多其他可能不允许用户连接到 80 以外的其他端口和 443,而这些端口上的任何非 http 流量都可能触发入侵检测系统。

当您出于某种原因仍想在同一个端口上处理两种协议时,会有点困难。 Websocket 是一个基于 TCP 的协议,起初看起来像一个普通的 HTTP GET 请求,直到您收到标头 Connection: UpgradeUpgrade: websocket

这意味着对于任一协议的连接请求首先需要被同一个侦听器接受。只有在客户端发送了足够的数据以将其连接尝试识别为您的自定义协议或 websocket(或完全不同的东西,意外连接到您的端口 - 当您部署面向互联网的应用程序时,您会遇到很多)然后委托与客户端通信到适当的处理程序类。

【讨论】:

我没有使用 Websocket 作为监听器,而是使用 WebSocket 作为客户端,它向我的 serverApplication 发送请求以建立连接,Javscript 代码:var socket = new WebSocket('ws://xxx.xxx.x.xx:11110/');。我做错了吗? @Bhushan 似乎您正在尝试使用同一端口上的同一侦听器处理 websocket 连接和您自己的协议。正如我写的那样,您可以这样做,但是为不同的协议使用不同的端口会更容易。这就是端口号的发明目的。【参考方案2】:

TcpClient 是一个 Socket 包装器。

WebSocket 是一种可以在 TcpClient 上运行的协议。 WebSocket 协议定义了握手以及如何构建数据。

区分简单 TCP 连接和 WebSocket 连接的最佳方法是让它们侦听不同的端口,因为您将使用不同的协议。如果你把它们放在同一个端口会很糟糕,它会变得一团糟。

【讨论】:

以上是关于区分 TcpClient 和 WebSocket?的主要内容,如果未能解决你的问题,请参考以下文章

tcpclient和socket的区别?

tcpclient和socket的区别

使用 C# 和 AWS 证书保护 WebSocket 服务器

Node.js Websocket 区分不同的用户

websocket client怎样维持心跳,有没有具体的栗子

WebSocket区分不同客户端方法