• WebSocket小叙


    概述

    刚看到WeSocket的时候,我以为是HTTP相关,但是在前两天搭了一个简单的Client之后, 我发现这不就是TCP长连接么? 建立连接->通信->断开连接. 直到今天, 我在调试的时候, 发现发出了HTTP请求, 我想, 事情可能不是我想的那样.

    先来简单描述一下当时的情况

    我用Python代码简单打了一个WebSocket 客户端, 想着试一试, 代码很简单, 就是这:

    import websocket
    import threading
    import time
    
    class Status:
        INIT = 'init'
        OPENED = 'opened'
        CLOSED = 'closed'
    
    class WSTest:
        def __init__(self):
            self.thread = None
            self.ping_thread = None
            self.ws = None
            self.status = Status.INIT
    
        def send_message(self, message) -> bool:
            if self.status != Status.OPENED:
                return False
            self.ws.send(message)
            return True
        def close(self):
            self.ws.close()
            # 等待关闭
            for i in range(200):
                time.sleep(0.02)
                if self.status == Status.CLOSED:
                    break
            if self.status != Status.CLOSED:
                return
            if self.ping_thread and self.ping_thread.is_alive():
                self.ping_thread.join()
        def run(self):
            def on_message(ws, message):
                print(message)
            def on_error(ws, error):
                print(error)
            def on_close(ws):
                print('关闭连接')
                self.status = Status.CLOSED
            def on_open(ws):
                self.status = Status.OPENED
            self.ws = websocket.WebSocketApp("ws://echo.websocket.org",
                                             on_open=on_open,
                                             on_message=on_message,
                                             on_close=on_close,
                                             on_error=on_error)
            self.ping_thread = threading.Thread(target=self.ws.run_forever, args=(None, None, 2, 5))
            self.ping_thread.start()
    
    if __name__ == "__main__":
        ws = WSTest()
        ws.run()
        while True:
            s = input()
            if s == 'close':
                break
            ws.send_message(s)
        ws.close()
    

    上面的ws://echo.websocket.org 是一个测试用的域名,你发送什么过去,他就会返回什么. 到这里我简单运行了一下,还可以.本来我想简单搭一个,能调通就得了呗,但是,手贱的我打开了wireshark. 我想看一下它的网络连接. 

    wireshark抓包查看

    首先,找到域名的IP

    找到IP后就可以直接对IP进行过滤,找到接收和发送的数据包.直接过滤所有DNS解析请求,查找指定域名.

    然后,针对地址对请求进行过滤

    来来来,看到了什么?前面三个TCP请求是三次握手的请求,在三次握手之后的第一个请求是什么,HTTP????

    看一下它的请求内容:

    看到第一个Upgrade之后,我仿佛懂了.这个字段的含义是要将协议升级.后面跟着的就是websocket了,再看一下服务器的response.(后面那个TCP请求可以跳过,就是服务器告诉你它收到了).

    响应内容虽然有不明白的地方,但是大概看来,是同意升级协议的意思了.再然后才是websocket通信内容,以及最后的挥手告别.

    也就是说,websocket虽然能够实现双向通信,但是它的连接建立是从HTTP开始,然后升级协议来的??

    所以websocket的通信流程是:

    1. 三次握手建立TCP通信
    2. 发起HTTP请求,升级为websokcet协议
    3. 开始websocket通信
    4. 断开连接

    如果把中间的websocket去掉,那就完全是HTTP协议了. 没想到websocketHTTP是兄弟俩.

    思考

    既然WebSocket是基于HTTP协议建立的, 那么他的出现就一定是在HTTP之后, 这就说明它一定是为了解决HTTP的某些问题而出现的. 很显然: HTTP的单向通信限制, 服务器不能主动联系客户端

    HTTP协议本身就是基于TCP的, 而TCP本身就是全双工通信的. 这感觉就像是他们借用了一下HTTP, 然后说咱们接下来就都用WebSocket吧.

    那么问题来了, 既然要实现这种长连接, 为什么还要借助HTTP之手, 直接TCP建立连接不行么? 查了一下, 发现是为了兼容. 因为WebSocket就是为了解决HTTP协议问题, 也就是说主要运行在之前HTTP的场景中, 而为了兼容现有浏览器的握手规范, 所以借助了HTTP协议来完成握手.

    WebSocket协议是: wswss. 其区别与 httphttps 相同. wss 就是在 ws 的通信过程中再套一层TLS/SSL 协议.

    那么WebSocket有哪些应用场景呢?

    可以这么说, 在原来使用HTTP协议进行轮训的场景, 都可以使用WebSocket替换.

    • 在线聊天
    • 直播
    • 在线多人游戏
    • 等等....

    最后, 记一下建立连接的HTTP请求的头信息

    request

    • connection: Upgrade 升级协议
    • Upgrade: websocket 指定升级为WebSocket协议
    • Sec-WebSocket-Key: 用于判断客户端是否有权升级协议
    • Sec-WebSocket-Version:指定WebSocket 版本

    response

    • Upgrade: websocket 成功升级协议
    • Sec-WebSocket-Accept: 通过Sec-WebSocket-Key计算得来
  • 相关阅读:
    001-导航条悬浮顶部
    000-导航栏单击事件背景变换
    1-MySQL命令行
    了解CentOS服务器的基本信息
    SecureCRT配色
    SecureCRT中文显示乱码
    Android Studio 1.1 使用介绍及导入 jar 包和第三方依赖库
    Android Json 解析
    不断更新中 书签
    Android 常用的权限
  • 原文地址:https://www.cnblogs.com/hujingnb/p/12494006.html
Copyright © 2020-2023  润新知