GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — fullstackpython.github.com/websockets.html at gh-pages · kevinisaac/fullstackpython.github.com Expand file tree/ Copy pathwebsockets.htmlMore file actions 367 lines (350 loc) · 24.4 KB / Copy pathwebsockets.htmlFile metadata and controls367 lines (350 loc) · 24.4 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 <!DOCTYPE html> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="Matt Makai"> <meta name="description" content="WebSockets are a protocol for full-duplex web communications. Learn about WebSockets on Full Stack Python."> <link rel="shortcut icon" href="theme/img/fsp-fav.png"> <title>WebSockets - Full Stack Python</title> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> <link href="theme/css/f.min.css" rel="stylesheet"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css" rel="stylesheet"> <style> .toc-indent {padding-left: 25px;} .toc-more-indent {padding-left: 37px;} </style> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-19910497-7', 'auto'); ga('send', 'pageview'); </script> </head> <body> <a href="https://github.com/makaimc/fullstackpython.github.com"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="logo-header-section"> <a href="/" style="text-decoration: none; border: none;"><img src="theme/img/fsp-logo.png" height="52" width="52" class="logo-image" style="padding-top: 1px;" alt="Full Stack Python logo"></a> <span class="logo-title"><a href="/">Full Stack Python</a></span> </div> </div> </div><div class="row"> <div class="col-md-8"> <h1>WebSockets</h1> <p>A WebSocket is a <a href="http://tools.ietf.org/html/rfc6455">standard protocol</a> for two-way data transfer between a client and server. The WebSockets protocol does not run over HTTP, instead it is a separate implementation on top of <a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a>.</p> <h2>Why use WebSockets?</h2> <p>A WebSocket connection allows full-duplex communication between a client and server so that either side can push data to the other through an established connection. The reason why WebSockets, along with the related technologies of <a href="http://en.wikipedia.org/wiki/Server-sent_events">Server-sent Events</a> (SSE) and <a href="https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-12">WebRTC data channels</a>, are important is that HTTP is not meant for keeping open a connection for the server to frequently push data to a web browser. Previously, most web applications would implement long polling via frequent Asynchronous JavaScript and XML (AJAX) requests as shown in the below diagram. </p> <p><img src="theme/img/ajax-long-polling.png" width="100%" alt="Long polling via AJAX is incredibly inefficient for some applications." class="technical-diagram" /></p> <p>Server push is more efficient and scalable than long polling because the web browser does not have to constantly ask for updates through a stream of AJAX requests.</p> <p><img src="theme/img/websockets-flow.png" width="100%" alt="WebSockets are more efficient than long polling for server sent updates." class="technical-diagram" /></p> <p>While the above diagram shows a server pushing data to the client, WebSockets is a full-duplex connection so the client can also push data to the server as shown in the diagram below.</p> <p><img src="theme/img/websockets-flow-with-client-push.png" width="100%" alt="WebSockets also allow client push in addition to server pushed updates." class="technical-diagram" /></p> <p>The WebSockets approach for server- and client-pushed updates works well for certain categories of web applications such as chat room, which is why that's often an example application for a WebSocket library.</p> <h2>Implementing WebSockets</h2> <p>Both the web browser and the server must implement the WebSockets protocol to establish and maintain the connection. There are important implications for servers since WebSockets connections are long lived, unlike typical HTTP connections. </p> <p>A multi-threaded or multi-process based server cannot scale appropriately for WebSockets because it is designed to open a connection, handle a request as quickly as possible and then close the connection. An asynchronous server such as <a href="http://www.tornadoweb.org/en/stable/">Tornado</a> or <a href="http://gunicorn.org/">Green Unicorn</a> monkey patched with <a href="http://www.gevent.org/">gevent</a> is necessary for any practical WebSockets server-side implementation.</p> <p>On the client side, it is not necessary to use a JavaScript library for WebSockets. Web browsers that implement WebSockets will expose all necessary client-side functionality through the <a href="http://www.w3.org/TR/2011/WD-websockets-20110419/">WebSockets object</a>. </p> <p>However, a JavaScript wrapper library can make a developer's life easier by implementing graceful degradation (often falling back to long-polling when WebSockets are not supported) and by providing a wrapper around browser-specific WebSocket quirks. Examples of JavaScript client libraries and WSGI implementations are found below.</p> <h2>JavaScript client libraries</h2> <ul> <li> <p><a href="http://socket.io/">Socket.io</a>'s client side JavaScript library can be used to connect to a server side WebSockets implementation.</p> </li> <li> <p><a href="https://github.com/gimite/web-socket-js">web-socket-js</a> is a Flash-based client-side WebSockets implementation.</p> </li> </ul> <h2>Nginx WebSocket proxying</h2> <p>Nginx officially supports WebSocket proxying as of <a href="http://nginx.com/blog/websocket-nginx/">version 1.3</a>. 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. </p> <p>Here are the configuration settings I use in my Nginx file as part of my WebSockets proxy.</p> <div class="codehilite"><pre><span class="cp"># this is where my WSGI server sits answering only on localhost</span> <span class="cp"># usually this is Gunicorn monkey patched with gevent</span> <span class="n">upstream</span> <span class="n">app_server_wsgiapp</span> <span class="p">{</span> <span class="n">server</span> <span class="n">localhost</span><span class="o">:</span><span class="mi">5000</span> <span class="n">fail_timeout</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="p">}</span> <span class="n">server</span> <span class="p">{</span> <span class="err">#</span> <span class="n">typical</span> <span class="n">web</span> <span class="n">server</span> <span class="n">configuration</span> <span class="n">goes</span> <span class="n">here</span> <span class="err">#</span> <span class="n">this</span> <span class="n">section</span> <span class="n">is</span> <span class="n">specific</span> <span class="n">to</span> <span class="n">the</span> <span class="n">WebSockets</span> <span class="n">proxying</span> <span class="n">location</span> <span class="o">/</span><span class="n">socket</span><span class="p">.</span><span class="n">io</span> <span class="p">{</span> <span class="n">proxy_pass</span> <span class="n">http</span><span class="o">:</span><span class="c1">//app_server_wsgiapp/socket.io;</span> <span class="n">proxy_redirect</span> <span class="n">off</span><span class="p">;</span> <span class="n">proxy_set_header</span> <span class="n">Host</span> <span class="err">$</span><span class="n">host</span><span class="p">;</span> <span class="n">proxy_set_header</span> <span class="n">X</span><span class="o">-</span><span class="n">Real</span><span class="o">-</span><span class="n">IP</span> <span class="err">$</span><span class="n">remote_addr</span><span class="p">;</span> <span class="n">proxy_set_header</span> <span class="n">X</span><span class="o">-</span><span class="n">Forwarded</span><span class="o">-</span><span class="n">For</span> <span class="err">$</span><span class="n">proxy_add_x_forwarded_for</span><span class="p">;</span> <span class="n">proxy_http_version</span> <span class="mf">1.1</span><span class="p">;</span> <span class="n">proxy_set_header</span> <span class="n">Upgrade</span> <span class="err">$</span><span class="n">http_upgrade</span><span class="p">;</span> <span class="n">proxy_set_header</span> <span class="n">Connection</span> <span class="s">"upgrade"</span><span class="p">;</span> <span class="n">proxy_read_timeout</span> <span class="mi">600</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <p>The following resources are also helpful for setting up the configuration properly.</p> <ul> <li> <p>Nginx has <a href="http://nginx.org/en/docs/http/websocket.html">an official page for WebSocket proxying</a>.</p> </li> <li> <p><a href="http://blog.martinfjordvald.com/2013/02/websockets-in-nginx/">WebSockets in Nginx</a> walks through the Nginx WebSockets configuration directives.</p> </li> <li> <p><a href="https://chrislea.com/2013/02/23/proxying-websockets-with-nginx/">Proxying WebSockets with Nginx</a> shows how to proxy with Socket.io.</p> </li> </ul> <h2>Open source Python examples with WebSockets</h2> <ul> <li> <p>The <a href="https://github.com/makaimc/python-websockets-example">python-websockets-example</a> contains code to create a simple web application that provides WebSockets using Flask, Flask-SocketIO and gevent.</p> </li> <li> <p>The Flask-SocketIO project has a <a href="https://github.com/miguelgrinberg/Flask-SocketIO/tree/master/example">chat web application</a> that demos sending server generated events as well as input from users via a text box input on a form.</p> </li> </ul> <h2>General WebSockets resources</h2> <ul> <li> <p>The official W3C <a href="http://www.w3.org/TR/websockets/">candidate draft for WebSockets API</a> and the <a href="http://dev.w3.org/html5/websockets/">working draft for WebSockets</a> 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.</p> </li> <li> <p><a href="http://lucumr.pocoo.org/2012/9/24/websockets-101/">WebSockets 101</a> 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.</p> </li> <li> <p>The "Can I Use?" website has a <a href="http://caniuse.com/#feat=websockets">handy WebSockets reference chart</a> for which web browsers and specific versions support WebSockets.</p> </li> <li> <p>Mozilla's <a href="https://developer.mozilla.org/en-US/docs/WebSockets">Developer Resources for WebSockets</a> is a good place to find documentation and tools for developing with WebSockets.</p> </li> <li> <p><a href="http://websocketd.com/">websocketd</a> is a WebSockets server aiming to be the "CGI of WebSockets". Worth a look.</p> </li> </ul> <h2>Python-specific WebSockets resources</h2> <ul> <li> <p><a href="http://mrjoes.github.io/2013/06/21/python-realtime.html">Real-time in Python</a> provides Python-specific context for how the server push updates were implemented in the past and how Python's tools have evolved to perform server side updates.</p> </li> <li> <p><a href="https://github.com/aaugustin/websockets">websockets</a> is a WebSockets implementation for Python 3.3+ written with the <a href="https://docs.python.org/3.4/library/asyncio.html">asyncio</a> module (or with <a href="https://code.google.com/p/tulip/">Tulip</a> if you're working with Python 3.3).</p> </li> <li> <p>The <a href="https://www.twilio.com/blog/2014/11/choose-your-own-adventure-presentations-with-reveal-js-python-and-websockets.html">Choose Your Own Adventure Presentations</a> tutorial uses WebSockets via gevent on the server and socketio.js for pushing vote count updates from the server to the client. </p> </li> <li> <p><a href="http://bottlepy.org/docs/dev/async.html">Async with Bottle</a> shows how to use greenlets to support WebSockets with the Bottle web framework.</p> </li> <li> <p>If you're deploying to Heroku, there is a <a href="https://devcenter.heroku.com/articles/python-websockets">specific WebSockets guide</a> for getting your Python application up and running.</p> </li> <li> <p>The <a href="http://www.reddit.com/r/Python/comments/2ujqd7/an_overview_of_using_websockets_in_python/">Reddit thread for this page</a> has some interesting comments on what's missing from the above content that I'm working to address.</p> </li> </ul> <h3>What's next for your web application after setting up WebSockets?</h3> <div class="row"> <div class="col-md-4"> <div class="well select-next"> <a href="/wsgi-servers.html" class="btn btn-success btn-full"><i class="fa fa-play fa-inverse fa-2x"></i></a> <p class="under-btn"> How do I execute Python since the web server doesn't do that? </p> </div> </div> <div class="col-md-4"> <div class="well select-next"> <a href="/application-dependencies.html" class="btn btn-success btn-full"><i class="fa fa-archive fa-inverse fa-2x"></i></a> </a> <p class="under-btn"> How should I install Python libraries on the server? </p> </div> </div> <div class="col-md-4"> <div class="well select-next"> <a href="/development-environments.html" class="btn btn-success btn-full"><i class="fa fa-desktop fa-2x"></i></a> <p class="under-btn"> What should I use to code my Python application? </p> </div> </div> </div> <div id="mc_embed_signup"> <form action="//mattmakai.us2.list-manage.com/subscribe/post?u=b7e774f0c4f05dcebbfee183d&id=b22335388d" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate> <div id="mc_embed_signup_scroll"> <h4>Sign up here to receive an email with major updates to this site and Python tutorials delivered to your inbox once a month.</h4> <div class="row"> <div class="col-md-9"> <input type="email" value="" name="EMAIL" class="email form-control" id="mce-EMAIL" placeholder="email address" required> <div style="position: absolute; left: -5000px;"><input type="text" name="b_b7e774f0c4f05dcebbfee183d_b22335388d" tabindex="-1" value=""></div> </div> <div class="col-md-3"> <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="btn btn-success" style="font-family: 'Helvetica Neue';"></div> </div> </div> </div> </form> </div> </div> <div class="col-md-offset-1 col-md-3" id="sidebar"> <div class="panel panel-success"> <div class="panel-heading"> <h3 class="panel-head"><a href="/table-of-contents.html" style="color: #fff;">Table of Contents</a></h3> </div> <div class="list-group"> <a href="/introduction.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Introduction</a> <a href="/why-use-python.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Why Use Python?</a> <a href="/best-python-resources.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Best Python Resources</a> <a href="/best-python-videos.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Best Python Videos</a> <a href="/development-environments.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Development Environments</a> <a href="/vim.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Vim</a> <a href="/emacs.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Emacs</a> <a href="/generators.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Generators</a> <a href="/comprehensions.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Comprehensions</a> <a href="/web-frameworks.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Web Frameworks</a> <a href="/django.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Django</a> <a href="/flask.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Flask</a> <a href="/bottle.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Bottle</a> <a href="/pyramid.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Pyramid</a> <a href="/morepath.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Morepath</a> <a href="/other-web-frameworks.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Other Web Frameworks</a> <a href="/web-design.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Web Design</a> <a href="/cascading-style-sheets.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Cascading Style Sheets</a> <a href="/javascript.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>JavaScript</a> <a href="/websockets.html" class="list-group-item smaller-item active" style='font-family: "Helvetica Neue",sans-serif;'>WebSockets</a> <a href="/web-application-security.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Web Application Security</a> <a href="/databases.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Databases</a> <a href="/no-sql-datastore.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>NoSQL Data Stores</a> <a href="/application-programming-interfaces.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Application Programming Interfaces</a> <a href="/api-integration.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>API Integration</a> <a href="/api-creation.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>API Creation</a> <a href="/deployment.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Deployment</a> <a href="/servers.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Servers</a> <a href="/platform-as-a-service.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Platform-as-a-service</a> <a href="/operating-systems.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Operating Systems</a> <a href="/web-servers.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Web Servers</a> <a href="/wsgi-servers.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>WSGI Servers</a> <a href="/source-control.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Source Control</a> <a href="/application-dependencies.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Application Dependencies</a> <a href="/static-content.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Static Content</a> <a href="/task-queues.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Task Queues</a> <a href="/configuration-management.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Configuration Management</a> <a href="/continuous-integration.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Continuous Integration</a> <a href="/logging.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Logging</a> <a href="/monitoring.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Monitoring</a> <a href="/web-analytics.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Web Analytics</a> <a href="/docker.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Docker</a> <a href="/caching.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Caching</a> <a href="/code-metrics.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Code Metrics</a> <a href="/what-full-stack-means.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>What "Full Stack" Means</a> <a href="/change-log.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Change Log</a> <a href="/future-directions.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>Future Directions</a> <a href="/about-author.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>About the Author</a> </div> </div> <div class="panel panel-success"> <div class="panel-heading"><h3 class="panel-head">WebSockets</h3></div> <div class="panel-body"> Major updates are tweeted via <a href="https://twitter.com/fullstackpython">@fullstackpython</a>. <hr/> Need more detailed tutorials than you see here? <a href="/email.html">Sign up to receive an email when that content is created.</a> </div> </div> </div></div> <hr/> <div class="footer pull-right"> <a href="http://www.mattmakai.com/" class="underline">Matt Makai</a> 2015 </div> </div> <script type='text/javascript'> var trackOutboundLink = function(url) { ga('send', 'event', 'outbound', 'click', url, {'hitCallback': function () { document.location = url; } }); } </script> </body> </html> |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |