WebSocket协议详解及应用(一)-初识WebSocket

本系列文章主要介绍WebSocket协议以及基于该协议的服务器端、客户端编程。服务器端代码采用的是PHP语言开发,Nginx做代理负责代理客户端与PHP脚本之间的数据通信;客户端语言为JavaScript,测试浏览器为Chrome。

一、什么是WebSocket

WebSocket是一个允许Web应用程序(通常指浏览器)与服务器进行双向通信的协议。HTML5的WebSocket API主要是为浏览器端提供了一个基于TCP协议实现全双工通信的方法。该技术的目标是为基于浏览器的双向通信应用提供一个不需要打开多个HTTP连接的机制。

二、优点

1.全双工通信
在传统的Web应用中,浏览器与服务器交互都是半双工通信(但并不完全是半双工通信,服务器无法主动向浏览器推送)。即同一时间内数据流向是单一的,浏览器向服务器发送请求后需要等待服务器返回数据。
而在WebSocket中,浏览器和服务器之间可随时进行通信,不必等待对方传送完毕,浏览器接收到服务器的数据后会自动触发onmessage事件。
2.实时性
传统的Web应用很难做到实时通信,通常是用长连接或轮询的方式进行。对于服务器来说,轮询法是被动传输数据,即使数据有更新,但浏览器还未发送请求,则消息无法进行实时推送。
3.更少的数据传输及更少的请求数
传统Web应用中浏览器与服务器进行数据交互通常需要经过以下几个步骤:

  1. DNS查询
  2. TCP三次握手
  3. 传送HTTP请求头
  4. 传送HTTP请求体(如果有)
  5. 服务器处理后传送响应头
  6. 服务器传送响应体
  7. 断开TCP连接

在WebSocket中进行交互通常为以下几个步骤:

  1. DNS查询
  2. TCP三次握手
  3. WebSocket握手
  4. 浏览器发送请求
  5. 服务器发送响应
  6. 断开TCP连接

从上面可以看到如果仅是一次通信,二者差异并不是很大,甚至WebSocket比普通方式还要多一次握手。但在需要频繁交互数据时,WebSocket的优势就显露出来了。
例如,当有10次数据交互时,前者最多可能要建立10个TCP连接,然后要发送10次请求头(包含Cookie等信息,数据量可能会达到KB级别),接收的响应信息可能才几个字节(如某些心跳包、空消息等),这样会极大的浪费带宽等资源。试想,如果你在做一个聊天应用,想要获取当前在线人数,你需要向服务器发送你的全部cookie(至少要几百个字节),除此之外HTTP头中还要包含其他信息,如URL、host等,这些都是必不可少的。最后服务器返回了几百个字节,但其中真正需要用到的只有不到10字节(只需要知道在线人数,其他信息都是无用的)。通过WebSocket,浏览器可以向服务器发送1~2字节的请求(不需要带上cookie验证身份,可以在握手时进行认证,一旦TCP连接建立,则在连接上的通信都是认证过身份的数据,这也是它的好处之一:便于服务端识别客户端的状态),这个请求仅包含一个特定的控制码(由开发者实现的应用层协议指定),服务器只需返回特定的返回码及数据即可,一切无用的字节都被省去。

三、应用场景
1.数据传输实时性要求较高
Web聊天室、直播实时弹幕、HTML5网络互动类游戏
2.推送类应用
网站消息通知、邮箱新邮件提醒
3.监控在线状态、精确统计在线时长
统计用户行为
4.远程调试代码、云指令系统
部分移动端调试工具是基于WebSocket开发(此处为WebSocket协议而非WebSocket API)
5.其他用途
网络(包括内网)嗅探(端口扫描)、僵尸网络及后门(云指令系统)

四、浏览器支持
IE:10+
Firefox:4+(11+完全支持)
Chrome:4+(16+完全支持)
Safari:5+(7+完全支持)
Opera:11.5+(12.1+完全支持)
Safari(iOS):4.3+(6.1+完全支持)
Android:4.4+
以上数据来源于caniuse.com

五、相关文档
WebSocket rfc6455
WebSocket WHATWG
WebSocket W3C(见WHATWG)

nginx变量索引表

此页面版本:2016-06-08

$ancient_browser
$arg_
$args
$binary_remote_addr
$body_bytes_sent
$bytes_sent (ngx_http_core_module)
$bytes_sent (ngx_http_log_module)
$connection (ngx_http_core_module)
$connection (ngx_http_log_module)
$connection_requests (ngx_http_core_module)
$connection_requests (ngx_http_log_module)
$connections_active
$connections_reading
$connections_waiting
$connections_writing
$content_length
$content_type
$cookie_
$date_gmt
$date_local
$document_root
$document_uri
$fastcgi_path_info
$fastcgi_script_name
$geoip_area_code
$geoip_city
$geoip_city_continent_code
$geoip_city_country_code
$geoip_city_country_code3
$geoip_city_country_name
$geoip_country_code
$geoip_country_code3
$geoip_country_name
$geoip_dma_code
$geoip_latitude
$geoip_longitude
$geoip_org
$geoip_postal_code
$geoip_region
$geoip_region_name
$gzip_ratio
$host
$hostname
$http2
$http_
$https
$invalid_referer
$is_args
$limit_rate
$memcached_key
$modern_browser
$msec (ngx_http_core_module)
$msec (ngx_http_log_module)
$msie
$nginx_version
$pid
$pipe (ngx_http_core_module)
$pipe (ngx_http_log_module)
$proxy_add_x_forwarded_for
$proxy_host
$proxy_port
$proxy_protocol_addr
$proxy_protocol_port
$query_string
$realip_remote_addr
$realip_remote_port
$realpath_root
$remote_addr
$remote_port
$remote_user
$request
$request_body
$request_body_file
$request_completion
$request_filename
$request_id
$request_length (ngx_http_core_module)
$request_length (ngx_http_log_module)
$request_method
$request_time (ngx_http_core_module)
$request_time (ngx_http_log_module)
$request_uri
$scheme
$secure_link
$secure_link_expires
$sent_http_
$server_addr
$server_name
$server_port
$server_protocol
$session_log_binary_id
$session_log_id
$slice_range
$spdy
$spdy_request_priority
$ssl_cipher
$ssl_client_cert
$ssl_client_fingerprint
$ssl_client_i_dn
$ssl_client_raw_cert
$ssl_client_s_dn
$ssl_client_serial
$ssl_client_verify
$ssl_protocol
$ssl_server_name
$ssl_session_id
$ssl_session_reused
$status (ngx_http_core_module)
$status (ngx_http_log_module)
$tcpinfo_rtt
$tcpinfo_rttvar
$tcpinfo_snd_cwnd
$tcpinfo_rcv_space
$time_iso8601 (ngx_http_core_module)
$time_iso8601 (ngx_http_log_module)
$time_local (ngx_http_core_module)
$time_local (ngx_http_log_module)
$uid_got
$uid_reset
$uid_set
$upstream_addr
$upstream_cache_status
$upstream_connect_time
$upstream_cookie_
$upstream_header_time
$upstream_http_
$upstream_response_length
$upstream_response_time
$upstream_status
$uri