socket.io的原理 的详细工作流程是怎样的

&img data-rawwidth=&510& data-rawheight=&382& src=&/v2-3ca0f3ee0aa9_b.jpg& class=&origin_image zh-lightbox-thumb& width=&510& data-original=&/v2-3ca0f3ee0aa9_r.jpg&&&br&&br&1876年法国赠送美国政府自由女神雕塑,女神体积很庞大,法国政府委托快递公司运输,先拆分成300片打包,编号为1-300,需要三艘船运输,第一艘运1-100片,以此类推。&br&&br&&b&场景一:三艘船按序到达&/b&&br&美国政府每天派人去快递公司查件&b&(Receive函数)&/b&,第一艘船到达,快递公司将1-100片交付美国政府,以此类推,收完300片,可以完整重构自由女神,传输任务完成。&br&&br&&b&场景二:三艘船乱序到达&/b&&br&由于第一艘船动力有点问题,结果最后达到,船到达顺序为2、3、1,假设委托人也是天天去查件,&b&在第一艘船没有到达之前,快递公司会假装什么都没有发生&/b&,直到第一艘船到达,然后按照船编号顺序将货物提交给委托人,与场景一相比,&b&会有大一些的延迟。&/b&&br&&br&&b&场景三:有一艘船掉大西洋里了&/b&&br&浩瀚的大西洋,波澜壮阔,掉一艘船到海里,天知,海知,你我他不知,第一艘、第三船都到达了,可是第二艘船却迟迟未到,一周过去了,一个月过去了,还是杳无音讯,快递公司美国分公司意识到出事了,他们做了两方面工作:&br&&br&1)将第一艘船的货物提交给美国政府&b&(在刚接收到就可以提交给美国政府)&/b&&br&2)派人通知法国总公司将第二艘船的货物再建造一份,雕塑编号为101-200,重新运输&br&&br&半个月之后,第二艘运输船到达了,然后提交给美国政府,最后是第三艘船的货物。&br&&br&&b&与场景一、二相比,传输的延迟最大。&/b&&br&&br&上文的故事,&b&法国政府代表客户端&/b&,负责发送大块数据给服务器端;&b&美国政府是服务器端&/b&,负责接收大块数据;&b&快递公司代表TCP&/b&,负责货物的按序提交给客户(应用程序),负责乱序的重新排序、以及丢包的超时重传。&br&&br&简单回答一下问题:&br&TCP接收方知道数据(字节流)的起始序列号,怎么知道的?&b&同步握手里有对方的ISN(Initial Sequence Number),&/b&所以会将接收到的数据按字节排好序(1,2,3…N)放入buffer,应用程序会通过receive函数来取走,至于取走多少,取决于buffer有多少数据,以及receive函数的入口长度字段。然后应用程序对拿到的字节流进行解释、分段。&br&&br&&br&续:&a href=&/question//answer/& class=&internal&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/question/3400&/span&&span class=&invisible&&3599/answer/&/span&&span class=&ellipsis&&&/span&&/a&
1876年法国赠送美国政府自由女神雕塑,女神体积很庞大,法国政府委托快递公司运输,先拆分成300片打包,编号为1-300,需要三艘船运输,第一艘运1-100片,以此类推。 场景一:三艘船按序到达 美国政府每天派人去快递公司查件(Receive函数),第一艘船到达,…
&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 是基于 WebSocket 的 C-S 实时通信库,我假设题目问的是 &a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 而非 WebSocket 协议的实现。&br&&br&&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 底层是 &a href=&///?target=http%3A//engine.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&engine.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&,这个库实现了跨平台的双向通信。&br&&a href=&///?target=http%3A//engine.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&engine.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 使用了 WebSocket 和 XMLHttprequest(或JSONP) 封装了一套自己的 Socket 协议(暂时叫 EIO Socket),在低版本浏览器里面使用长轮询替代 WebSocket。一个完整的 EIO Socket 包括多个 XHR 和 WebSocket 连接.&br&&br&前端:&br&&br&EIO Socket 通过一个 XHR (XMLHttprequest) 握手。前端发送一个 XHR,告诉服务端我要开始 XHR 长轮询了。后端返回的数据里面包括一个 open 标志(数字 0 表示), 以及一个 sid 和 upgrades 字段。&br&sid 是本次 EIO Socket 的会话 ID,因为一次 EIO Socket 包含了多个请求,而后端又会同时连接多个 EIO Socket,sid 的作用就相当于 SESSION ID。&br&另一个字段 upgrades,正常情况下是 ['websocket'],表示可以把连接方式从长轮询升级到 WebSocket.&br&&br&前端在发送第一个 XHR 的时候就开始了 XHR 长轮询,这个时候如果有收发数据的需求,是通过长轮询实现的。所谓长轮询,是指前端发送一个 request,服务端会等到有数据需要返回时再 response. 前端收到 response 后马上发送下一次 request。这样就可以实现双向通信。&br&&br&前端收到握手的 upgrades 后,EIO 会检测浏览器是否支持 WebSocket,如果支持,就会启动一个 WebSocket 连接,然后通过这个 WebSocket 往服务器发一条内容为 probe, 类型为 ping 的数据。如果这时服务器返回了内容为 probe, 类型为 pong 的数据,前端就会把前面建立的 HTTP 长轮询停掉,后面只使用 WebSocket 通道进行收发数据。&br&EIO Socket 生命周期内,会间隔一段时间 ping - pong 一次,用来测试网络是否正常。&br&&br&&img src=&/9ed419a25fb3c88c79ba3ee6d336b59f_b.png& data-rawwidth=&344& data-rawheight=&278& class=&content_image& width=&344&&这是 WebSocket 帧的结构,绿色是发送,白色是接收。前面的数字是数据包类型,2 是 ping, 3 是 pong, 4 是 message.&br&&br&&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 在 &a href=&///?target=http%3A//engine.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&engine.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 的基础上做了一些封装,比如 &a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 里面这样的代码:&br&&div class=&highlight&&&pre&&code class=&language-as&&&span class=&nx&&io&/span&&span class=&p&&.&/span&&span class=&nx&&emit&/span&&span class=&p&&(&/span&&span class=&s1&&'add user'&/span&&span class=&o&&,&/span& &span class=&s1&&'m'&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&在 engine.io 里面是这样:&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&nx&&eio&/span&&span class=&p&&.&/span&&span class=&nx&&send&/span&&span class=&p&&(&/span&&span class=&s1&&'message'&/span&&span class=&p&&,&/span& &span class=&s1&&'2[&add user&,&m&]'&/span&&span class=&p&&)&/span& &span class=&c1&&// 2 是 socket.io 定义的包类型&/span&
&/code&&/pre&&/div&&br&再例如,engine.io-client 需要在 open 之后才能 send,而 &a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 就不需要,open 之前 emit 的数据会在 open 之后再发出。&br&&br&另外 &a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 还提供了 namespace,复用, 自动重连等特性。&br&&br&服务端:&br&&br&服务端使用 &a href=&///?target=https%3A///websockets/ws& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ws&i class=&icon-external&&&/i&&/a& 库实现 WebSocket 协议。&br&&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 服务启动时,会先启动一个 ws 服务。&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 会监听 HTTP 服务器的 &a href=&///?target=https%3A//nodejs.org/api/http.html%23http_event_upgrade& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&upgrade&i class=&icon-external&&&/i&&/a& 和 &a href=&///?target=https%3A//nodejs.org/api/http.html%23http_event_request& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&request&i class=&icon-external&&&/i&&/a& 事件。&br&当 upgrade 事件触发时,说明可能是 WebSocket 握手,先简单校验下,然后把请求交给 ws 服务进行处理,拿到 WebSocket 对象。&br&当 request 事件触发时,根据 url 路径判断是不是 &a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 的 XHR 请求,拿到 res 和 res 对象。&br&这样就可以正确接收和返回客户端数据了,具体处理过程和前端部分是对应的。
是基于 WebSocket 的 C-S 实时通信库,我假设题目问的是
而非 WebSocket 协议的实现。
底层是 ,这个库实现了跨平台的双向通信。
使用了 WebSoc…
理论上,如果你发了100个包,第一个没到,后面的先到了,那就都缓存着,API表现为你什么都没收到。要么第一个包重发后尽快到达,要么buffer满了傻逼,要么服务器自己觉得太久了决定掉线。
理论上,如果你发了100个包,第一个没到,后面的先到了,那就都缓存着,API表现为你什么都没收到。要么第一个包重发后尽快到达,要么buffer满了傻逼,要么服务器自己觉得太久了决定掉线。
1. 因为网络IO操作很慢,内存操作很快(几十纳秒)&br&2. 几个线程处理上万连接,主要是指有很多不忙的连接的场景,如聊天室服务器。&br&3. 如果有耗费CPU的处理,要单开线程处理,可以使用线程池避免建立销毁线程的开销。当线程都忙时还可以加入等待队列&br&4. 如果都上万连接都很忙,处理还是计算密集型的,这个就不成立了。&br&5.异步IO和多路复用降低的是开大量线程处理请求(一线程一客户端)方式带来的内存开销和频繁上下文切换的CPU开销。&br&&br&关于异步IO和多路复用可以参考&a href=&/question//answer/& class=&internal&&I/O多路复用技术(multiplexing)是什么? - 用心阁的回答&/a&&br&关于epoll和select的区别可以参考&a href=&/question//answer/& class=&internal&&为什么select打开的FD数量有限制,而poll、epoll等打开的FD数量没有限制? - 用心阁的回答&/a&
1. 因为网络IO操作很慢,内存操作很快(几十纳秒) 2. 几个线程处理上万连接,主要是指有很多不忙的连接的场景,如聊天室服务器。 3. 如果有耗费CPU的处理,要单开线程处理,可以使用线程池避免建立销毁线程的开销。当线程都忙时还可以加入等待队列 4. 如果…
从我们在&a href=&///?target=http%3A//& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Teambition&i class=&icon-external&&&/i&&/a& 的实践经验来看,最终使用&a href=&///?target=http%3A//sockjs.org& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&sockjs&i class=&icon-external&&&/i&&/a& 替换了socket.io,内存控制上更好一些。&br&&br&Quora上有一个不错的回答供参考, &a href=&///?target=http%3A///Sock-js/What-are-the-pros-and-cons-of-socket-io-vs-sockjs& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/Sock-js/What-&/span&&span class=&invisible&&are-the-pros-and-cons-of-socket-io-vs-sockjs&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&
从我们在 的实践经验来看,最终使用 替换了socket.io,内存控制上更好一些。 Quora上有一个不错的回答供参考,
epoll 比 select 效率高,仅仅是因为 epoll 的实现更合理而已。和你的业务处理没关系。&br&&br&如果你的业务处理很耗 CPU 的话,那当然只能等着啦。只不过大部分互联网软件绝大部分时间都在等待网络 I/O 而不是缺少 CPU 资源。闲着也是闲着,不如多处理几个请求啦。
epoll 比 select 效率高,仅仅是因为 epoll 的实现更合理而已。和你的业务处理没关系。 如果你的业务处理很耗 CPU 的话,那当然只能等着啦。只不过大部分互联网软件绝大部分时间都在等待网络 I/O 而不是缺少 CPU 资源。闲着也是闲着,不如多处理几个请求啦。
最近项目有用到socket做上传,就我理解的来说说,如有问题请指正并原谅俺~&br&流程大致是这样的:&br&&ol&&li&服务端启动一个socket服务,并监听'connection'事件。&/li&&li&客户端(一般指浏览器)创建一个websocket,并连接服务器端的socket,并绑定接收socket事件的方法。&/li&&li&客户连接后,服务端socket就可以向客户端发消息了。&/li&&/ol&socket通讯可以简单的理解为一个真正意义上的长链接,不主动断开的话该通道一直存在,并且通道的两端可以互相喊话。&br&&br&普通的请求比如http\xhr这类的,是一个一次性的通讯,当通讯完成后,通道会关闭。&br&socket一次通讯后并不会关闭通道,这就是他们的区别所在。&br&当然不同的通讯有不同的协议,此处就不展开了(其实是我没怎么了解...)。&br&&br&&a href=&///?target=http%3A//socket.io/docs/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Socket.IO
Docs&i class=&icon-external&&&/i&&/a& 官网给的demo很明白了。&br&&br&服务端&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&kd&&var&/span& &span class=&nx&&app&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'http'&/span&&span class=&p&&).&/span&&span class=&nx&&createServer&/span&&span class=&p&&(&/span&&span class=&nx&&handler&/span&&span class=&p&&)&/span&
&span class=&kd&&var&/span& &span class=&nx&&io&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'socket.io'&/span&&span class=&p&&)(&/span&&span class=&nx&&app&/span&&span class=&p&&);&/span&
&span class=&kd&&var&/span& &span class=&nx&&fs&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'fs'&/span&&span class=&p&&);&/span&
&span class=&nx&&app&/span&&span class=&p&&.&/span&&span class=&nx&&listen&/span&&span class=&p&&(&/span&&span class=&mi&&80&/span&&span class=&p&&);&/span&
&span class=&c1&&// 创建socket,监听连接&/span&
&span class=&nx&&io&/span&&span class=&p&&.&/span&&span class=&nx&&on&/span&&span class=&p&&(&/span&&span class=&s1&&'connection'&/span&&span class=&p&&,&/span& &span class=&kd&&function&/span& &span class=&p&&(&/span&&span class=&nx&&socket&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// 收到连接后,触发 'news' 事件&/span&
&span class=&nx&&socket&/span&&span class=&p&&.&/span&&span class=&nx&&emit&/span&&span class=&p&&(&/span&&span class=&s1&&'news'&/span&&span class=&p&&,&/span& &span class=&p&&{&/span& &span class=&nx&&hello&/span&&span class=&o&&:&/span& &span class=&s1&&'world'&/span& &span class=&p&&});&/span&
&span class=&c1&&// 接收客户端事件&/span&
&span class=&nx&&socket&/span&&span class=&p&&.&/span&&span class=&nx&&on&/span&&span class=&p&&(&/span&&span class=&s1&&'my other event'&/span&&span class=&p&&,&/span& &span class=&kd&&function&/span& &span class=&p&&(&/span&&span class=&nx&&data&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&data&/span&&span class=&p&&);&/span&
&span class=&p&&});&/span&
&span class=&p&&});&/span&
&/code&&/pre&&/div&&br&客户端&br&&div class=&highlight&&&pre&&code class=&language-js&&
&span class=&kd&&var&/span& &span class=&nx&&socket&/span& &span class=&o&&=&/span& &span class=&nx&&io&/span&&span class=&p&&(&/span&&span class=&s1&&'http://localhost'&/span&&span class=&p&&);&/span&
&span class=&c1&&// 自定义一个'news'事件&/span&
&span class=&nx&&socket&/span&&span class=&p&&.&/span&&span class=&nx&&on&/span&&span class=&p&&(&/span&&span class=&s1&&'news'&/span&&span class=&p&&,&/span& &span class=&kd&&function&/span& &span class=&p&&(&/span&&span class=&nx&&data&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&data&/span&&span class=&p&&);&/span&
&span class=&c1&&// 发送事件到服务端&/span&
&span class=&nx&&socket&/span&&span class=&p&&.&/span&&span class=&nx&&emit&/span&&span class=&p&&(&/span&&span class=&s1&&'my other event'&/span&&span class=&p&&,&/span& &span class=&p&&{&/span& &span class=&nx&&my&/span&&span class=&o&&:&/span& &span class=&s1&&'data'&/span& &span class=&p&&});&/span&
&span class=&p&&});&/span&
&/code&&/pre&&/div&&br&当然实际应用中远远不止如此简单,以我目前的知识储备,可以推荐的是将socket当作一个类http服务,不同的请求可以当成router+handle的方法来处理,这样就不会有一堆乱七八糟的的on\emit了。&br&&br&&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&官方也推荐使用namespace来区分多个处理服务。
最近项目有用到socket做上传,就我理解的来说说,如有问题请指正并原谅俺~ 流程大致是这样的: 服务端启动一个socket服务,并监听'connection'事件。客户端(一般指浏览器)创建一个websocket,并连接服务器端的socket,并绑定接收socket事件的方法。客户连…
问题有点奇怪,理一理&br&&br&ws 和 wss 均为 WebSocket 协议的 schema,一个是非安全的,一个是安全的&br&tcp + ws as ws,tcp + tls + ws as wss,可以和 http 协议对比理解&br&&br&&a href=&///?target=http%3A//Socket.IO& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&Socket.IO&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 算是基于 WebSocket 进行扩展的协议吧,ws 和 wss 要理解为两种不同协议的话,他都支持&br&&br&refs:&br&&a href=&///?target=http%3A//socket.io/%23faq& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io/#&/span&&span class=&invisible&&faq&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&br&&a href=&///?target=http%3A//dev.w3.org/html5/websockets/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&dev.w3.org/html5/websoc&/span&&span class=&invisible&&kets/&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&
问题有点奇怪,理一理 ws 和 wss 均为 WebSocket 协议的 schema,一个是非安全的,一个是安全的 tcp + ws as ws,tcp + tls + ws as wss,可以和 http 协议对比理解
算是基于 WebSocket 进行扩展的协议吧,ws 和 wss 要理解为两种不同…
问题解决,wireshark能抓到包,混在了tcp当中(它不识别webSoket), 但是是明文传输的!&br&还好不是压缩的.好像数据以 .N 开头 (不确定)
16进制为:814e &br&&img src=&/b073e231bd9e90bc1a0a486e_b.png& data-rawwidth=&346& data-rawheight=&92& class=&content_image& width=&346&&&br&&br&终于搞定了:说下webSocket建立以后不再有tcp连接建立:&br&&img src=&/45f72a02c_b.png& data-rawwidth=&759& data-rawheight=&137& class=&origin_image zh-lightbox-thumb& width=&759& data-original=&/45f72a02c_r.png&&所以,上图中,如果把webSocket这条记录清空了,然后,不管后台发什么数据都不会再建立连接了.&br&&img src=&/4f07c96e9e8b375b16fefa_b.png& data-rawwidth=&974& data-rawheight=&159& class=&origin_image zh-lightbox-thumb& width=&974& data-original=&/4f07c96e9e8b375b16fefa_r.png&&正确的做法是,先打开 调试窗口,再选中websock连接,然后选中Frames,&br&每发一个消息,都有记录了!
问题解决,wireshark能抓到包,混在了tcp当中(它不识别webSoket), 但是是明文传输的! 还好不是压缩的.好像数据以 .N 开头 (不确定) 16进制为:814e 终于搞定了:说下webSocket建立以后不再有tcp连接建立: 所以,上图中,如果把webSocket这条记录清空了,然后,不管…
&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& 在github上有一些比较简陋的文档 &a href=&///?target=https%3A///learnboost/socket.io/wiki& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&LearnBoost/socket.io Wiki&i class=&icon-external&&&/i&&/a&&br&据G&a href=&///?target=https%3A///guille& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&uille&i class=&icon-external&&&/i&&/a&多月前在邮件列表中称 伴随1.0发布会提供一个全新的doc站点&br&&br&如有必要 不如我们在github上见一个public的repo来做一个中文的&a href=&///?target=http%3A//socket.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&socket.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&文档如何?
在github上有一些比较简陋的文档
据G多月前在邮件列表中称 伴随1.0发布会提供一个全新的doc站点 如有必要 不如我们在github上见一个public的repo来做一个中文的文档如何?
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 socket工作流程 的文章

 

随机推荐