nginx配置
配置如下
server {
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://websocket_upstream;
}
}
服务器
客户端
使用telnet,例子如下
GET /websocket_upgrade HTTP/1.1
Host: localhost
Connection: Upgrade
Upgrade: websocket
HTTP/1.1 101 Switching Protocols
Server: BaseHTTP/0.6 Python/3.6.8
Date: Tue, 29 Oct 2019 14:59:42 GMT
Upgrade: websocket
Connection: Upgrade
Content-type: text/html
Connection: keep-alive
GET / HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Server: BaseHTTP/0.6 Python/3.6.8
Date: Tue, 29 Oct 2019 15:00:00 GMT
Content-type: text/html
Content-Length: 6
Connection: keep-alive
hello
nginx实现
/* 处理后端的响应 */
ngx_http_proxy_process_header() {
/* 如果返回 101 */
if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS) {
u->keepalive = 0;
/* 如果存在connection: upgrade */
if (r->headers_in.upgrade) {
u->upgrade = 1; /* !! nginx支持upgrade */
}
}
}
ngx_http_upstream_send_response()
{
if(u->upgrade) {
ngx_http_upstream_upgrade(r, u); /* 升级的核心 */
return;
}
}
ngx_http_upstream_upgrade() {
/* 关键在与设置read/write处理函数 */
u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;
}
/*以上函数是对这个函数的包装,调用参数不同,就是从一个socket读,写入令一个socket,实际上可以splice 或者 socket map*/
ngx_http_upstream_process_upgraded(ngx_http_request_t *r, ngx_uint_t from_upstream, ngx_uint_t do_write)
nginx检查响应,如果响应码是101,并且头部有"connection: upgrade",那么就将连接升级,然后连接就是从一个socket往另一个socket搬运数据。
参考文献
websocket协议rfc翻译 https://juejin.im/post/5c6b7366e51d45016527d648