{"id":1643,"date":"2018-04-09T13:31:15","date_gmt":"2018-04-09T05:31:15","guid":{"rendered":"http:\/\/www.yueguangzu.net\/?p=1643"},"modified":"2018-04-15T22:35:15","modified_gmt":"2018-04-15T14:35:15","slug":"%e4%bd%bf%e7%94%a8tornado%e6%90%ad%e5%bb%ba%e7%ae%80%e5%8d%95%e7%9a%84websocket","status":"publish","type":"post","link":"http:\/\/www.yueguangzu.net\/?p=1643","title":{"rendered":"\u4f7f\u7528Tornado\u642d\u5efa\u7b80\u5355\u7684WebSocket"},"content":{"rendered":"<h4 class=\"md-end-block md-heading md-focus\"><span class=\"md-expand\">\u4ec0\u4e48\u662fWebSocket?<\/span><\/h4>\n<h5 class=\"md-end-block md-heading\">WebSocket\u534f\u8bae\u662f\u57fa\u4e8eTCP\u7684\u4e00\u79cd\u65b0\u7684\u7f51\u7edc\u534f\u8bae\u3002\u5b83\u5b9e\u73b0\u4e86\u6d4f\u89c8\u5668\u4e0e\u670d\u52a1\u5668\u5168\u53cc\u5de5(full-duplex)\u901a\u4fe1\u2014\u2014\u5141\u8bb8\u670d\u52a1\u5668\u4e3b\u52a8\u53d1\u9001\u4fe1\u606f\u7ed9\u5ba2\u6237\u7aef\u3002WebSocket\u901a\u4fe1\u534f\u8bae\u4e8e2011\u5e74\u88ab<a spellcheck=\"false\" href=\"https:\/\/baike.baidu.com\/item\/IETF\">IETF<\/a>\u5b9a\u4e3a\u6807\u51c6RFC 6455\uff0c\u5e76\u88abRFC7936\u6240\u8865\u5145\u89c4\u8303\u3002<\/h5>\n<h5 class=\"md-end-block md-heading\">WebSocket\u534f\u8bae\u652f\u6301\uff08\u5728\u53d7\u63a7\u73af\u5883\u4e2d\u8fd0\u884c\u4e0d\u53d7\u4fe1\u4efb\u7684\u4ee3\u7801\u7684\uff09<strong>\u5ba2\u6237\u7aef<\/strong>\u4e0e\uff08\u9009\u62e9\u52a0\u5165\u8be5\u4ee3\u7801\u7684\u901a\u4fe1\u7684\uff09<strong>\u8fdc\u7a0b\u4e3b\u673a<\/strong>\u4e4b\u95f4\u8fdb\u884c<strong>\u5168\u53cc\u5de5\u901a\u4fe1<\/strong>\u3002\u7528\u4e8e\u6b64\u7684\u5b89\u5168\u6a21\u578b\u662fWeb\u6d4f\u89c8\u5668\u5e38\u7528\u7684\u57fa\u4e8e\u539f\u59cb\u7684\u5b89\u5168\u6a21\u5f0f\u3002 \u534f\u8bae\u5305\u62ec\u4e00\u4e2a\u5f00\u653e\u7684\u63e1\u624b\u4ee5\u53ca\u968f\u540e\u7684TCP\u5c42\u4e0a\u7684\u6d88\u606f\u5e27\u3002 \u8be5\u6280\u672f\u7684\u76ee\u6807\u662f\u4e3a\u57fa\u4e8e\u6d4f\u89c8\u5668\u7684\u3001\u9700\u8981\u548c\u670d\u52a1\u5668\u8fdb\u884c\u53cc\u5411\u901a\u4fe1\u7684\uff08<strong>\u670d\u52a1\u5668<\/strong>\u4e0d\u80fd\u4f9d\u8d56\u4e8e\u6253\u5f00\u591a\u4e2aHTTP\u8fde\u63a5\uff08\u4f8b\u5982\uff0c\u4f7f\u7528XMLHttpRequest\u6216<span class=\"md-tag\" spellcheck=\"false\">&lt;iframe&gt;<\/span>\u548c\u957f\u8f6e\u8be2\uff09\uff09\u5e94\u7528\u7a0b\u5e8f\u63d0\u4f9b\u4e00\u79cd\u901a\u4fe1\u673a\u5236\u3002<\/h5>\n<h5 class=\"md-end-block md-heading\">\u957f\u4e45\u4ee5\u6765, \u521b\u5efa\u5b9e\u73b0\u5ba2\u6237\u7aef\u548c\u7528\u6237\u7aef\u4e4b\u95f4\u53cc\u5de5\u901a\u8baf\u7684web app\u90fd\u4f1a\u9020\u6210HTTP\u8f6e\u8be2\u7684\u6ee5\u7528: \u5ba2\u6237\u7aef\u5411\u4e3b\u673a\u4e0d\u65ad\u53d1\u9001\u4e0d\u540c\u7684HTTP\u547c\u53eb\u6765\u8fdb\u884c\u8be2\u95ee\u3002<\/h5>\n<blockquote><p><span class=\"md-line md-end-block\">\u8fd9\u4f1a\u5bfc\u81f4\u4e00\u7cfb\u5217\u7684\u95ee\u9898\uff1a<\/span><\/p>\n<p><span class=\"md-line md-end-block\">1.\u670d\u52a1\u5668\u88ab\u8feb\u4e3a\u6bcf\u4e2a\u5ba2\u6237\u7aef\u4f7f\u7528\u8bb8\u591a\u4e0d\u540c\u7684\u5e95\u5c42TCP\u8fde\u63a5\uff1a\u4e00\u4e2a\u7528\u4e8e\u5411\u5ba2\u6237\u7aef\u53d1\u9001\u4fe1\u606f\uff0c\u5176\u5b83\u7528\u4e8e\u63a5\u6536\u6bcf\u4e2a\u4f20\u5165\u6d88\u606f\u3002<\/span><\/p>\n<p><span class=\"md-line md-end-block\">2.\u6709\u4e9b\u534f\u8bae\u6709\u5f88\u9ad8\u7684\u5f00\u9500\uff0c\u6bcf\u4e00\u4e2a\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u4e4b\u95f4\u90fd\u6709HTTP\u5934\u3002<\/span><\/p>\n<p><span class=\"md-line md-end-block\">3.\u5ba2\u6237\u7aef\u811a\u672c\u88ab\u8feb\u7ef4\u62a4\u4ece\u4f20\u51fa\u8fde\u63a5\u5230\u4f20\u5165\u8fde\u63a5\u7684\u6620\u5c04\u6765\u8ffd\u8e2a\u56de\u590d\u3002<\/span><\/p>\n<p><span class=\"md-line md-end-block\">\u4e00\u4e2a\u66f4\u7b80\u5355\u7684\u89e3\u51b3\u65b9\u6848\u662f\u4f7f\u7528<strong>\u5355\u4e2aTCP\u8fde\u63a5<\/strong>\u53cc\u5411\u901a\u4fe1\u3002 \u8fd9\u5c31\u662fWebSocket\u534f\u8bae\u6240\u63d0\u4f9b\u7684\u529f\u80fd\u3002 \u7ed3\u5408WebSocket API \uff0cWebSocket\u534f\u8bae\u63d0\u4f9b\u4e86\u4e00\u4e2a\u7528\u6765\u66ff\u4ee3HTTP\u8f6e\u8be2\u5b9e\u73b0\u7f51\u9875\u5230\u8fdc\u7a0b\u4e3b\u673a\u7684\u53cc\u5411\u901a\u4fe1\u7684\u65b9\u6cd5\u3002<\/span><\/p>\n<p><span class=\"md-line md-end-block\">WebSocket\u534f\u8bae\u88ab\u8bbe\u8ba1\u6765\u53d6\u4ee3\u7528HTTP\u4f5c\u4e3a\u4f20\u8f93\u5c42\u7684\u53cc\u5411\u901a\u8baf\u6280\u672f,\u8fd9\u4e9b\u6280\u672f\u53ea\u80fd\u727a\u7272\u6548\u7387\u548c\u53ef\u4f9d\u8d56\u6027\u5176\u4e2d\u4e00\u65b9\u6765\u63d0\u9ad8\u53e6\u4e00\u65b9\uff0c\u56e0\u4e3aHTTP\u6700\u521d\u7684\u76ee\u7684\u4e0d\u662f\u4e3a\u4e86\u53cc\u5411\u901a\u8baf\u3002\uff08\u83b7\u5f97\u66f4\u591a\u5173\u4e8e\u6b64\u7684\u8ba8\u8bba\u53ef\u67e5\u9605RFC6202)<\/span><\/p><\/blockquote>\n<h4 class=\"md-end-block md-heading\">\u5b9e\u73b0\u539f\u7406<\/h4>\n<blockquote><p><span class=\"md-line md-end-block\">\u5728\u5b9e\u73b0websocket\u8fde\u7ebf\u8fc7\u7a0b\u4e2d\uff0c\u9700\u8981\u901a\u8fc7\u6d4f\u89c8\u5668\u53d1\u51fawebsocket\u8fde\u7ebf\u8bf7\u6c42\uff0c\u7136\u540e\u670d\u52a1\u5668\u53d1\u51fa\u56de\u5e94\uff0c\u8fd9\u4e2a\u8fc7\u7a0b\u901a\u5e38\u79f0\u4e3a\u201c\u63e1\u624b\u201d \u3002\u5728 WebSocket API\uff0c\u6d4f\u89c8\u5668\u548c\u670d\u52a1\u5668\u53ea\u9700\u8981\u505a\u4e00\u4e2a\u63e1\u624b\u7684\u52a8\u4f5c\uff0c\u7136\u540e\uff0c\u6d4f\u89c8\u5668\u548c\u670d\u52a1\u5668\u4e4b\u95f4\u5c31\u5f62\u6210\u4e86\u4e00\u6761\u5feb\u901f\u901a\u9053\u3002\u4e24\u8005\u4e4b\u95f4\u5c31\u76f4\u63a5\u53ef\u4ee5\u6570\u636e\u4e92\u76f8\u4f20\u9001\u3002\u5728\u6b64WebSocket \u534f\u8bae\u4e2d\uff0c\u4e3a\u6211\u4eec\u5b9e\u73b0\u5373\u65f6\u670d\u52a1\u5e26\u6765\u4e86\u4e24\u5927\u597d\u5904\uff1a<\/span><\/p>\n<ol class=\"ol-list\">\n<li><span class=\"md-line md-end-block\">Header<\/span><\/li>\n<\/ol>\n<p><span class=\"md-line md-end-block\">\u4e92\u76f8\u6c9f\u901a\u7684Header\u662f\u5f88\u5c0f\u7684-\u5927\u6982\u53ea\u6709 2 Bytes<\/span><\/p>\n<ol class=\"ol-list\" start=\"2\">\n<li><span class=\"md-line md-end-block\">Server Push<\/span><\/li>\n<\/ol>\n<p><span class=\"md-line md-end-block\">\u670d\u52a1\u5668\u7684\u63a8\u9001\uff0c\u670d\u52a1\u5668\u4e0d\u518d\u88ab\u52a8\u7684\u63a5\u6536\u5230\u6d4f\u89c8\u5668\u7684\u8bf7\u6c42\u4e4b\u540e\u624d\u8fd4\u56de\u6570\u636e\uff0c\u800c\u662f\u5728\u6709\u65b0\u6570\u636e\u65f6\u5c31\u4e3b\u52a8\u63a8\u9001\u7ed9\u6d4f\u89c8\u5668\u3002<\/span><\/p><\/blockquote>\n<h5 class=\"md-end-block md-heading\">python\u540e\u53f0\u4ee3\u7801<\/h5>\n<h5 class=\"md-end-block md-heading\">1.\u9996\u5148\u8981\u642d\u5efa\u4e00\u4e2a\u670d\u52a1\u5668,\u4f7f\u7528tornado\u642d\u5efa\u670d\u52a1\u5668\u4ee3\u7801\u5982\u4e0b,<span spellcheck=\"false\"><code>\u642d\u5efa\u670d\u52a1\u5668\u4ee3\u7801\u5982\u6709\u4e0d\u660e\u8bf7\u7559\u8a00<\/code><\/span><\/h5>\n<h5 class=\"md-end-block md-heading\">2.\u4f7f\u7528\u589e\u52a02\u4e2aHandler<\/h5>\n<h5 class=\"md-end-block md-heading\">MainHandler:\u7528\u6765\u5b9e\u73b0\u63a7\u5236\u9875\u9762\u8df3\u8f6c\u5230websocket\u4e3b\u9875<\/h5>\n<h5 class=\"md-end-block md-heading\">WSHandler:\u7528\u6765\u63a7\u5236\u63a5\u53d7\u524d\u7aefwebsocket\u7684\u903b\u8f91<\/h5>\n<blockquote>\n<h5 class=\"md-end-block md-heading\">\u5176\u4e2dWSHandler\u9700\u8981\u7ee7\u627ftornado.websocket.WebSocketHandler\u5bf9\u8c61,\u5e76\u91cd\u5199open,on_message,on_close<\/h5>\n<h5 class=\"md-end-block md-heading\">\u5173\u952e\u662fon_message\u65b9\u6cd5,\u662f\u5904\u7406\u6d88\u606f\u5230\u6765\u65f6\u5019\u7684\u903b\u8f91<\/h5>\n<h5 class=\"md-end-block md-heading\">\u5185\u7f6ewrite_message\u662f\u5f80\u524d\u7aef\u53d1\u9001\u6570\u636e\u4f7f\u7528\u7684\u65b9\u6cd5.<\/h5>\n<\/blockquote>\n<pre class=\"md-fences md-end-block\" lang=\"python\" contenteditable=\"false\"><span class=\"cm-comment\">#-*-coding:utf-8-*-<\/span>\r\n<span class=\"cm-keyword\">from<\/span> <span class=\"cm-variable\">tornado<\/span>.<span class=\"cm-property\">websocket<\/span> <span class=\"cm-keyword\">import<\/span> <span class=\"cm-variable\">WebSocketHandler<\/span>\r\n<span class=\"cm-keyword\">from<\/span> <span class=\"cm-variable\">tornado<\/span>.<span class=\"cm-property\">web<\/span> <span class=\"cm-keyword\">import<\/span> <span class=\"cm-variable\">RequestHandler<\/span>\r\n<span class=\"cm-keyword\">from<\/span> <span class=\"cm-variable\">tornado<\/span> <span class=\"cm-keyword\">import<\/span> <span class=\"cm-variable\">ioloop<\/span>,<span class=\"cm-variable\">httpserver<\/span>,<span class=\"cm-variable\">web<\/span>\r\n<span class=\"cm-keyword\">from<\/span> <span class=\"cm-variable\">tornado<\/span>.<span class=\"cm-property\">options<\/span> <span class=\"cm-keyword\">import<\/span> <span class=\"cm-variable\">define<\/span>,<span class=\"cm-variable\">options<\/span>\r\n\u200b\r\n<span class=\"cm-variable\">define<\/span>(<span class=\"cm-string\">'port'<\/span>,<span class=\"cm-variable\">default<\/span>=<span class=\"cm-string\">'6666'<\/span>,<span class=\"cm-builtin\">help<\/span>=<span class=\"cm-string\">'run port'<\/span>,<span class=\"cm-builtin\">type<\/span>=<span class=\"cm-builtin\">int<\/span>)\r\n<span class=\"cm-variable\">define<\/span>(<span class=\"cm-string\">'runserver'<\/span>,<span class=\"cm-variable\">default<\/span>=<span class=\"cm-builtin\">True<\/span>,<span class=\"cm-builtin\">help<\/span>=<span class=\"cm-string\">'run server'<\/span>,<span class=\"cm-builtin\">type<\/span>=<span class=\"cm-builtin\">bool<\/span>)\r\n\u200b\r\n<span class=\"cm-keyword\">class<\/span> <span class=\"cm-def\">WSHandler<\/span>(<span class=\"cm-variable\">WebSocketHandler<\/span>):\r\n \u00a0  <span class=\"cm-variable\">users<\/span>=<span class=\"cm-builtin\">set<\/span>()\r\n \u00a0  <span class=\"cm-keyword\">def<\/span> <span class=\"cm-builtin\">open<\/span>(<span class=\"cm-variable-2\">self<\/span>):\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">WSHandler<\/span>.<span class=\"cm-property\">users<\/span>.<span class=\"cm-property\">add<\/span>(<span class=\"cm-variable-2\">self<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">print<\/span>(<span class=\"cm-string\">'connected'<\/span>)\r\n \u00a0  <span class=\"cm-keyword\">def<\/span> <span class=\"cm-def\">on_message<\/span>(<span class=\"cm-variable-2\">self<\/span>, <span class=\"cm-variable\">message<\/span>):\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">print<\/span>(<span class=\"cm-variable-2\">self<\/span>.<span class=\"cm-property\">request<\/span>.<span class=\"cm-property\">remote_ip<\/span>,<span class=\"cm-variable\">message<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">for<\/span> <span class=\"cm-variable\">u<\/span> <span class=\"cm-keyword\">in<\/span> <span class=\"cm-variable-2\">self<\/span>.<span class=\"cm-property\">users<\/span>:\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">u<\/span>.<span class=\"cm-property\">write_message<\/span>(<span class=\"cm-string\">'[%s]:%s'<\/span><span class=\"cm-operator\">%<\/span>(<span class=\"cm-variable-2\">self<\/span>.<span class=\"cm-property\">request<\/span>.<span class=\"cm-property\">remote_ip<\/span>,<span class=\"cm-variable\">message<\/span>))\r\n \u00a0  <span class=\"cm-keyword\">def<\/span> <span class=\"cm-def\">on_close<\/span>(<span class=\"cm-variable-2\">self<\/span>):\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">print<\/span>(<span class=\"cm-string\">'8888'<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">WSHandler<\/span>.<span class=\"cm-property\">users<\/span>.<span class=\"cm-property\">remove<\/span>(<span class=\"cm-variable-2\">self<\/span>)\r\n<span class=\"cm-keyword\">class<\/span> <span class=\"cm-def\">MainHandler<\/span>(<span class=\"cm-variable\">RequestHandler<\/span>):\r\n \u00a0  <span class=\"cm-keyword\">def<\/span> <span class=\"cm-def\">get<\/span>(<span class=\"cm-variable-2\">self<\/span>):\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">self<\/span>.<span class=\"cm-property\">render<\/span>(<span class=\"cm-string\">'websocket.html'<\/span>)\r\n\u200b\r\n\u200b\r\n<span class=\"cm-variable\">handlers<\/span>=[\r\n \u00a0  (<span class=\"cm-string\">r'\/ws'<\/span>,<span class=\"cm-variable\">WSHandler<\/span>),\r\n \u00a0  (<span class=\"cm-string\">r'\/'<\/span>,<span class=\"cm-variable\">MainHandler<\/span>),\r\n]\r\n\u200b\r\n<span class=\"cm-keyword\">if<\/span> <span class=\"cm-variable\">__name__<\/span> == <span class=\"cm-string\">'__main__'<\/span>:\r\n \u00a0  <span class=\"cm-variable\">options<\/span>.<span class=\"cm-property\">parse_command_line<\/span>()\r\n \u00a0  <span class=\"cm-keyword\">if<\/span> <span class=\"cm-variable\">options<\/span>.<span class=\"cm-property\">runserver<\/span>:\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">app<\/span>=<span class=\"cm-variable\">web<\/span>.<span class=\"cm-property\">Application<\/span>(<span class=\"cm-variable\">handlers<\/span>=<span class=\"cm-variable\">handlers<\/span>,<span class=\"cm-variable\">debug<\/span>=<span class=\"cm-builtin\">True<\/span>,<span class=\"cm-variable\">template_path<\/span>=<span class=\"cm-string\">'..\/templates'<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">httpser<\/span>=<span class=\"cm-variable\">httpserver<\/span>.<span class=\"cm-property\">HTTPServer<\/span>(<span class=\"cm-variable\">app<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">httpser<\/span>.<span class=\"cm-property\">listen<\/span>(<span class=\"cm-variable\">options<\/span>.<span class=\"cm-property\">port<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">print<\/span>(<span class=\"cm-string\">'running...'<\/span>)\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">ioloop<\/span>.<span class=\"cm-property\">IOLoop<\/span>.<span class=\"cm-property\">instance<\/span>().<span class=\"cm-property\">start<\/span>()<\/pre>\n<h4 class=\"md-end-block md-heading\">\u524d\u7aef\u4ee3\u7801<\/h4>\n<blockquote>\n<h5 class=\"md-end-block md-heading\">1.\u524d\u7aef\u4e3b\u8981\u7684\u95ee\u9898\u5c31\u662f\u5f15\u7528<span spellcheck=\"false\"><code>WebSocket<\/code><\/span>\u5bf9\u8c61,\u5e76\u521d\u59cb\u5316\u4f20\u5165\u7684\u5730\u5740<\/h5>\n<h5 class=\"md-end-block md-heading\">2.\u524d\u7aef\u540c\u6837\u9700\u8981\u5b9a\u4e493\u4e2a\u65b9\u6cd5:onopen,onmessage,onclose\u5bf9\u5e94\u540e\u7aef\u7684open,on_message,on_close<\/h5>\n<h5 class=\"md-end-block md-heading\">3.\u53d1\u9001\u6d88\u606f\u4f7f\u7528send\u65b9\u6cd5<\/h5>\n<\/blockquote>\n<pre class=\"md-fences md-end-block\" lang=\"html\" contenteditable=\"false\"> \u00a0 \u00a0 \u00a0  var ws=new WebSocket('ws:\/\/127.0.0.1:6666\/ws');\r\n \u00a0 \u00a0 \u00a0  ws.onopen=function(){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  $('.status').html('\u5df2\u8fde\u63a5\u670d\u52a1\u5668');\r\n \u00a0 \u00a0 \u00a0  };\r\n \u00a0 \u00a0 \u00a0  ws.onmessage=function(mes){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  $('.ul').append('<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">li<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>'+ mes.data +'<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">li<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>');\r\n\u200b\r\n \u00a0 \u00a0 \u00a0  };\r\n \u00a0 \u00a0 \u00a0  ws.onclose=function(){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 $('.status').html('\u8fde\u63a5\u5df2\u65ad\u5f00');\r\n \u00a0 \u00a0 \u00a0  };<\/pre>\n<pre class=\"md-fences md-end-block\" lang=\"html\" contenteditable=\"false\"><span class=\"cm-meta\">&lt;!DOCTYPE html&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">html<\/span> <span class=\"cm-attribute\">lang<\/span>=<span class=\"cm-string\">\"en\"<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">head<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">meta<\/span> <span class=\"cm-attribute\">charset<\/span>=<span class=\"cm-string\">\"UTF-8\"<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">title<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>WebSocket<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">title<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">script<\/span> <span class=\"cm-attribute\">src<\/span>=<span class=\"cm-string\">\"http:\/\/cdn.static.runoob.com\/libs\/jquery\/1.9.0\/jquery.js\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;\/<\/span><span class=\"cm-tag\">script<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">style<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n\u200b\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.main<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">width<\/span>: <span class=\"cm-number\">500px<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">300px<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">border<\/span>: <span class=\"cm-number\">1px<\/span> <span class=\"cm-atom\">solid<\/span> <span class=\"cm-keyword\">red<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">border-radius<\/span>: <span class=\"cm-number\">5px<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">margin<\/span>: <span class=\"cm-number\">100px<\/span> <span class=\"cm-atom\">auto<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.status<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">position<\/span>: <span class=\"cm-atom\">relative<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">text-align<\/span>: <span class=\"cm-atom\">center<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">border<\/span>: <span class=\"cm-number\">1px<\/span> <span class=\"cm-atom\">dashed<\/span> <span class=\"cm-keyword\">grey<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">38px<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.bottom<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">margin-bottom<\/span>: <span class=\"cm-number\">0px<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">25px<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.send<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">width<\/span>: <span class=\"cm-number\">100%<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">100%<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">border<\/span>: <span class=\"cm-atom\">none<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">background-color<\/span>: <span class=\"cm-keyword\">palevioletred<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">font-size<\/span>: <span class=\"cm-number\">14px<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">font-family<\/span>: <span class=\"cm-string\">\"Microsoft Yahei\"<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">color<\/span>: <span class=\"cm-keyword\">whitesmoke<\/span>;\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">border-radius<\/span>: <span class=\"cm-number\">5px<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.down<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">25px<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-qualifier\">.ul<\/span>{\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-property\">height<\/span>: <span class=\"cm-number\">60%<\/span>;\r\n \u00a0 \u00a0 \u00a0  }\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">style<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">head<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">body<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n\u200b\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">h1<\/span> <span class=\"cm-attribute\">align<\/span>=<span class=\"cm-string\">\"center\"<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>WebSocket\u804a\u5929\u5ba4<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">h1<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">div<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"main\"<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">div<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"status\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;\/<\/span><span class=\"cm-tag\">div<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">ul<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"ul\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;\/<\/span><span class=\"cm-tag\">ul<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">div<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"down\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;<\/span><span class=\"cm-tag\">input<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"input\"<\/span> <span class=\"cm-attribute\">type<\/span>=<span class=\"cm-string\">\"text\"<\/span> <span class=\"cm-attribute\">size<\/span>=<span class=\"cm-string\">\"79\"<\/span> <span class=\"cm-attribute\">placeholder<\/span>=<span class=\"cm-string\">\"\u8bf7\u8f93\u5165\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;\/<\/span><span class=\"cm-tag\">div<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">div<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"bottom\"<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;<\/span><span class=\"cm-tag\">button<\/span> <span class=\"cm-attribute\">class<\/span>=<span class=\"cm-string\">\"send\"<\/span> <span class=\"cm-tag cm-bracket\">&gt;<\/span>\u53d1\u9001\u4fe1\u606f<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">button<\/span><span class=\"cm-tag cm-bracket\">&gt;&lt;\/<\/span><span class=\"cm-tag\">div<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">div<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n\u200b\r\n<span class=\"cm-tag cm-bracket\">&lt;<\/span><span class=\"cm-tag\">script<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-keyword\">function<\/span>(){\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">var<\/span> <span class=\"cm-def\">ws<\/span><span class=\"cm-operator\">=<\/span><span class=\"cm-keyword\">new<\/span> <span class=\"cm-variable\">WebSocket<\/span>(<span class=\"cm-string\">'ws:\/\/127.0.0.1:6666\/ws'<\/span>);\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">ws<\/span>.<span class=\"cm-property\">onopen<\/span><span class=\"cm-operator\">=<\/span><span class=\"cm-keyword\">function<\/span>(){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.status'<\/span>).<span class=\"cm-property\">html<\/span>(<span class=\"cm-string\">'\u5df2\u8fde\u63a5\u670d\u52a1\u5668'<\/span>);\r\n \u00a0 \u00a0 \u00a0  };\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">ws<\/span>.<span class=\"cm-property\">onmessage<\/span><span class=\"cm-operator\">=<\/span><span class=\"cm-keyword\">function<\/span>(<span class=\"cm-def\">mes<\/span>){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.ul'<\/span>).<span class=\"cm-property\">append<\/span>(<span class=\"cm-string\">'&lt;li&gt;'<\/span><span class=\"cm-operator\">+<\/span> <span class=\"cm-variable-2\">mes<\/span>.<span class=\"cm-property\">data<\/span> <span class=\"cm-operator\">+<\/span><span class=\"cm-string\">'&lt;\/li&gt;'<\/span>);\r\n\u200b\r\n \u00a0 \u00a0 \u00a0  };\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">ws<\/span>.<span class=\"cm-property\">onclose<\/span><span class=\"cm-operator\">=<\/span><span class=\"cm-keyword\">function<\/span>(){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.status'<\/span>).<span class=\"cm-property\">html<\/span>(<span class=\"cm-string\">'\u8fde\u63a5\u5df2\u65ad\u5f00'<\/span>);\r\n \u00a0 \u00a0 \u00a0  };\r\n\u200b\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.send'<\/span>).<span class=\"cm-property\">on<\/span>(<span class=\"cm-string\">'click'<\/span>,<span class=\"cm-keyword\">function<\/span>(){\r\n \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">ws<\/span>.<span class=\"cm-property\">send<\/span>( <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.input'<\/span>).<span class=\"cm-property\">val<\/span>());\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.input'<\/span>).<span class=\"cm-property\">val<\/span>(<span class=\"cm-string\">''<\/span>);\r\n \u00a0 \u00a0 \u00a0  })\r\n \u00a0 \u00a0 \u00a0  <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.input'<\/span>).<span class=\"cm-property\">bind<\/span>(<span class=\"cm-string\">'keypress'<\/span>,<span class=\"cm-keyword\">function<\/span>(<span class=\"cm-def\">event<\/span>){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-keyword\">if<\/span>(<span class=\"cm-variable-2\">event<\/span>.<span class=\"cm-property\">keyCode<\/span><span class=\"cm-operator\">==<\/span><span class=\"cm-string\">\"13\"<\/span>){\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">event<\/span>.<span class=\"cm-property\">preventDefault<\/span>();\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  <span class=\"cm-variable-2\">ws<\/span>.<span class=\"cm-property\">send<\/span>( <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.input'<\/span>).<span class=\"cm-property\">val<\/span>());\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"cm-variable\">$<\/span>(<span class=\"cm-string\">'.input'<\/span>).<span class=\"cm-property\">val<\/span>(<span class=\"cm-string\">''<\/span>);\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  }\r\n \u00a0 \u00a0 \u00a0  })\r\n \u00a0  })\r\n<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">script<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">body<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span>\r\n<span class=\"cm-tag cm-bracket\">&lt;\/<\/span><span class=\"cm-tag\">html<\/span><span class=\"cm-tag cm-bracket\">&gt;<\/span><\/pre>\n<h5 class=\"md-end-block md-heading\"><\/h5>\n<h5 class=\"md-end-block md-heading\"><\/h5>\n<h5 class=\"md-end-block md-heading\">\u5176\u5b83\u6846\u67b6(\u4f8b\u5982Django)\u540e\u7eed\u9646\u7eed\u66f4\u65b0,\u5982\u679c\u6709\u9700\u8981\u7684\u8bdd&#8230;&#8230;<\/h5>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1648\" src=\"http:\/\/www.yueguangzu.net\/wp-content\/uploads\/2018\/04\/111111.jpg\" alt=\"\" width=\"788\" height=\"492\" srcset=\"http:\/\/www.yueguangzu.net\/wp-content\/uploads\/2018\/04\/111111.jpg 788w, http:\/\/www.yueguangzu.net\/wp-content\/uploads\/2018\/04\/111111-300x187.jpg 300w, http:\/\/www.yueguangzu.net\/wp-content\/uploads\/2018\/04\/111111-768x480.jpg 768w\" sizes=\"(max-width: 788px) 100vw, 788px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4ec0\u4e48\u662fWebSocket? WebSocket\u534f\u8bae\u662f\u57fa\u4e8eTCP\u7684\u4e00\u79cd\u65b0\u7684\u7f51\u7edc\u534f\u8bae\u3002\u5b83\u5b9e\u73b0\u4e86\u6d4f\u89c8\u5668\u4e0e\u670d\u52a1\u5668\u5168\u53cc\u5de5(full-duplex)\u901a\u4fe1\u2014\u2014\u5141\u8bb8\u670d\u52a1\u5668\u4e3b\u52a8\u53d1\u9001\u4fe1\u606f\u7ed9\u5ba2\u6237\u7aef\u3002WebSocket\u901a\u4fe1\u534f\u8bae\u4e8e2011\u5e74\u88abIETF\u5b9a\u4e3a\u6807\u51c6RFC  [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[54],"tags":[56,108,107],"_links":{"self":[{"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/posts\/1643"}],"collection":[{"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1643"}],"version-history":[{"count":4,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/posts\/1643\/revisions"}],"predecessor-version":[{"id":1652,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=\/wp\/v2\/posts\/1643\/revisions\/1652"}],"wp:attachment":[{"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1643"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.yueguangzu.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}