websocket与http比较
相同点
- 传输层都是tcp协议
websocket的优点
- 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
>
重要的是Connection和Upgrade两个字段。
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个字节。
查看链接情况
可以看到tcp链接有保持住。
tcpdump抓包分析
第10个包,服务器主动关闭了tcp链接,是因为nginx默认websocket使用的长链接超时时间是60秒, 从第6个包到第10个包,刚好是60秒。
TODO
服务器的主动推送功能本文中没有详细介绍。