WebSockets

WebSocket是客户机和服务器间双向数据传输的标准协议。WebSockets协议不是运行在HTTP上,而是在TCP上直接运行。

为什么使用WebSockets?

WebSocket链接允许客户机和服务器间的全双工通信,链接建立后,任一方都可以把数据传给另一方。为什么WebSockets,Server-sent Events (SSE) 和WebRTC data channels至关重要,是因为HTTP不会维持一个开发连接把数据传给浏览器。之前,大多数网络应用会通过AJAX执行一个长链接,如下图。Long polling via AJAX is incredibly inefficient for some applications.

相对比长连接,服务器端推送更有效也更容易扩展,因为浏览器无需频繁的发送AJAX请求。WebSockets are more efficient than long polling for server sent updates.

上图显示了服务器推送数据到客户机,WebSockets是全双工连接,所有客户机也能推送数据到服务器,如下图。

WebSockets also allow client push in addition to server pushed updates.

WebSockets方式对于某些web应用非常好,比如网络聊天室,这也常被用来作为WebSockets的应用实例。

WebSockets实现

浏览器端和服务器端都必须实现WebSockets协议来维持连接。

一个多线程或多处理器的服务器不能很好的扩展WebSockets,因为它被设计成建立连接,快速处理请求,然后关闭连接。异步服务器比如Tornado 或 Green Unicorn monkey patched with gevent 可以很好的实现WebSockets服务器端执行。

客户机端,并不需要为WebSockets使用JavaScript库。实现WebSockets的浏览器会通过WebSockets object实现功能。

JavaScript客户端库

  • Socket.io 客户端JavaScript库能用与建立与服务器端的WebSockets连接。
  • web-socket-js 是一个基于Flash开发的客户端WebSockets实现。

Python实现

Nginx WebSocket proxying

Nginx officially supports WebSocket proxying as of version 1.3. However, you have to configure the Upgrade and Connection headers to ensure requests are passed through Nginx to your WSGI server. It can be tricky to set this up the first time.

Here are the configuration settings I use in my Nginx file as part of my WebSockets proxy.

# this is where my WSGI server sits answering only on localhost
# usually this is Gunicorn monkey patched with gevent
upstream app_server_wsgiapp {
  server localhost:5000 fail_timeout=0;
}

server {

  # typical web server configuration goes here

  # this section is specific to the WebSockets proxying
  location /socket.io {
    proxy_pass http://app_server_wsgiapp/socket.io;
    proxy_redirect off;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 600;
  }
}

Note if you run into any issues with the above example configuration you’ll want to scope out the official HTTP proxy module documentation.

The following resources are also helpful for setting up the configuration properly.

Open source Python examples with WebSockets

  • The python-websockets-example contains code to create a simple web application that provides WebSockets using Flask, Flask-SocketIO and gevent.
  • The Flask-SocketIO project has a chat web application that demos sending server generated events as well as input from users via a text box input on a form.

General WebSockets resources

  • The official W3C candidate draft for WebSockets API and the working draft for WebSockets are good reference material but can be tough for those new to the WebSockets concepts. I recommend reading the working draft after looking through some of the more beginner-friendly resources list below.
  • WebSockets 101 by Armin Ronacher provides a detailed assessment of the subpar state of HTTP proxying in regards to WebSockets. He also discusses the complexities of the WebSockets protocol including the packet implementation.
  • The “Can I Use?” website has a handy WebSockets reference chart for which web browsers and specific versions support WebSockets.
  • Mozilla’s Developer Resources for WebSockets is a good place to find documentation and tools for developing with WebSockets.
  • WebSockets from Scratch gives a nice overview of the protocol then shows how the lower-level pieces work with WebSockets, which are often a black box to developers who only use libraries like Socket.IO.
  • websocketd is a WebSockets server aiming to be the “CGI of WebSockets”. Worth a look.

Python-specific WebSockets resources