nginx支持websocket

479 阅读1分钟

websocket与http比较

相同点

  1. 传输层都是tcp协议

websocket的优点

  1. websocket是双向的,支持服务器主动向客户端发送数据

websocket应用场景

实时 Web 应用:Client 跟 Server 之间,实时的双向通信,例如 IM 等及时消息。

nginx配置文件

#user  nobody;
worker_processes  4;

events {
    worker_connections  1024;
}

http {
    #include       mime.types;
    #default_type  application/octet-stream;
    
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    
    server {
        client_max_body_size 4G;
	listen 8001;        # 故意设置为8001端口,方便抓包 
	root /data;

        proxy_set_header Upgrade $http_upgrade;  # 支持http协议提升到websocket 
        proxy_set_header Connection "upgrade";   #
	
    	location / {
    		autoindex on;
    		autoindex_exact_size on;
    		autoindex_localtime on;
    	}	
    }
    
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
}

使用CURL测试

curl --noproxy "*" -H 'Connection: keep-alive, Upgrade' -H 'Upgrade: websocket' -v -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: websocket' http://127.0.0.1:8001

因为电脑的配置了http代理,则在curl命令中使用noproxy来绕过代理,直接访问8001端口

http_proxy=http://127.0.0.1:7890
https_proxy=http://127.0.0.1:7890

http请求头如下:

> GET / HTTP/1.1
> Host: 127.0.0.1:8001
> User-Agent: curl/7.64.1
> Accept: */*
> Connection: keep-alive, Upgrade  # 此处多了Upgrade,表示从http协议升级
> Upgrade: websocket               # 此处表明从http协议升级到websocket协议
> Sec-WebSocket-Version: 13
> Sec-WebSocket-Key: websocket
>

重要的是ConnectionUpgrade两个字段。

http响应体如下:

< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Fri, 24 Dec 2021 15:24:03 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked     # 默认使用chunk协议
< Connection: keep-alive         # 使用http长链接
<

通过wireshark分析pcap包可以发现,确实使用了chunk协议, chunksize是474个字节。

image.png

查看链接情况

image.png

可以看到tcp链接有保持住。

tcpdump抓包分析

image.png

第10个包,服务器主动关闭了tcp链接,是因为nginx默认websocket使用的长链接超时时间是60秒, 从第6个包到第10个包,刚好是60秒。

TODO

服务器的主动推送功能本文中没有详细介绍。