WebSocket 协议

译者: coderbee (wen866595@163.com)
转载请注明出处

翻译自: http://tools.ietf.org/rfc/rfc6455.txt

Internet Engineering Task Force (IETF)                                                       I. Fette
Request for Comments: 6455                                                                      Google, Inc.
Category: Standards Track                                                                          A. Melnikov
ISSN: 2070-1721 Isode Ltd.                                                                         December 2011

WebSocket 协议

摘要

WebSocket协议使在控制环境下运行不受信任代码的客户端和能够选择与那些代码通信的远程主机之间能够双向通信。用于这个的安全模型是以origin为基础的安全模型,一般被浏览器使用。协议包含打开握手,其次是基本消息框架,在 TCP 之上。这项技术的目的是为基于浏览器的、需要与服务器双向通信的应用程序提供一种不依赖于打开多个HTTP连接的机制(例如,使用XMLHttpRequest 或 <iframe> 和长轮询)。

本备忘录的状态

这是一个Internet标准跟踪文件。

这个文档是因特网工程师任务组(IETF)的一个产品。它代表了IETF社区的共识。它已接受公众审查,因特网工程指导组(IESG)证明可出版。关于互联网标准的进一步信息在RFC5741的第2章节。

关于本文档当前状态的信息、勘误表和如何提供反馈,可以在 http://www.rfc-editor.org/info/rfc6455 找到。

版权声明

Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

1 介绍

1.1 背景

这部分是不规范的。

历史上,创建需要在客户端和服务器间双向通信的网络应用程序(如即时消息和游戏程序)要求滥用 HTTP 来轮询服务器来获得更新,通过不同 HTTP 请求来发送上行通知。

这导致各种问题:

  • 服务器被迫为每个客户端使用一些不同的底层TCP连接:一个用来向客户端发送消息,为每个到来的消息使用一个新的。
  • 通信(wire)协议具有很高的开销,因为每个客户端到服务器的消息有HTTP头。
  • 客户端侧的脚本被迫维护输出连接到输入连接的映射来追踪响应。

一个简单的解决方法是为双向传输使用单一的TCP连接。这是WebSocket协议提供的。结合WebSocket API(WSAPI),它为web页面到远程服务器的双向通信提供了HTTP轮询的替代方案。

同样的技术也可用于各种web应用程序:游戏,股票行情,多用户协同编辑的应用程序,用户界面实时展示服务器侧服务等。

WebSocket协议设计用来取代使用HTTP作为传输层的双向通信技术,并从现有的基础设施(代理、过滤、认证)受益。这些技术作为效率与可靠性的平衡而实现,因为HTTP最初并不是用于双向通信的(见RFC6202有多更讨论)。WebSocket尝试解决在现有HTTP基础设施的环境下现有HTTP双向通信技术的目标;像这样,它设计来工作于HTTP 80443端口上,并支持HTTP代理和中间设施,即使这意味着增加现有环境的一些复杂性。然而,设计并没有将WebSocket局限于HTTP,未来的实现可以在特定的端口上使用更简单的握手,而不需要重新发明整个协议。最后一点是重要的,因为交互式消息的传输模式并不紧密符合标准的HTTP传输,会在一些部件上引起异常的负载。

继续阅读WebSocket 协议

websoket的握手与数据传输格式

握手阶段就是普通的HTTP

客户端发送消息:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13
服务端返回消息:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
这里的Sec-WebSocket-Accept的计算方法是:

base64(hsa1(sec-websocket-key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11))

如果这个Sec-WebSocket-Accept计算错误浏览器会提示:

Sec-WebSocket-Accept dismatch

如果返回成功,Websocket就会回调onopen事件

 

websocket的数据传输使用的协议是:

18093511-13d8644ca2344a79a24d50bbae85ef12

参数的具体说明在这: 继续阅读websoket的握手与数据传输格式

Discuz 采集帖子后,分散作者,时间

有些Discuz站长为了丰富站点内容,会从其它站点抓取帖子。比如使用火车头程序等。这样做会有两个问题,发布的时间十分接近,发布作者一样。导致浏览站点的人一看便知,数据是从别处抓取的。为了分散时间与作者,在采集完数据后,可在数据库中执行下列SQL,可将数据分散。

//将指定人的帖子时间分散,authorid=2是 uid=2的用户
update `yhw_forum_thread` set dateline=(1284744665+ROUND(RAND() *1000000000)%97701546) WHERE authorid=2;
update `yhw_forum_thread` set lastpost=dateline WHERE authorid=2;
//将指定人的帖子的作者分散,authorid=2是 uid=2的用户
update yhw_forum_thread set `authorid` = ROUND(RAND() *10000)%(select max(uid) from yhw_common_member) where authorid=2;
//下面这句是将不在用户表中的authorid,重新生成。要反复执行多次,直到反更新的条目为0,
update yhw_forum_thread set `authorid` = ROUND(RAND() *10000)%(select max(uid) from yhw_common_member)
WHERE `authorid` not in (select uid from yhw_common_member);
//根据authorid重新生成author和lastposter
update `yhw_forum_thread` set author=(select username from yhw_common_member where uid=authorid),
lastposter=(select username from yhw_common_member where uid=authorid);
//更新forum_post,使author、authorid、dateline与forum_thread一致
update `yhw_forum_post` p set author=(select author from `yhw_forum_thread` t where t.tid=p.tid),
authorid=(select authorid from `yhw_forum_thread` t where t.tid=p.tid),
dateline=(select dateline from `yhw_forum_thread` t where t.tid=p.tid);

除去Discuz域名中的目录路径

一般在空间安装discuz会将其安装在根目录中,使用域名映射到根目录上。这时没有什么问题。但如果为了在一个空间中多放几个网站,一般会为每个网站创建一个目录,将各个网站的域名映射到对应的目录上。使用该方法可以在一个空间中安装多个discuz。但此时访问discuz时,一般会在域名后面多出来一个该discuz所在的目录,如将在个discuz安装在bbscenter目录中,对应的域名为bbs.daahe.com,此时访问该discuz时,将会出来诸如http://bbs.daahe.com/bbscenter/forum.php的路径。
为了解决该问题,可采用如下方法:
1、找到source/class/discuz/discuz_application.php文件。
2、打开该文件,找到private function _init_env() 方法。
3、找到如下代码处:

define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
define('ICONV_ENABLE', function_exists('iconv'));
define('MB_ENABLE', function_exists('mb_convert_encoding'));
define('EXT_OBGZIP', function_exists('ob_gzhandler'));
define('TIMESTAMP', time());

4、在此代码后加: define(‘SUB_DIR’, ‘/bbscenter/’); //bbscenter是该应用所有目录

css实现书籍目录效果,点线自适应

其实实现起来很简单。要求点线长度自适应。仔细看看,我的点线还是有些问题的,不完整。不知道如何解决,图片么?
75290c1a45ceec468718bf58
代码实现如下:
css:

*{margin:0;padding:0;}
body{font:12px Arial;}
ul{list-style:none;}
.menu{width:600px;margin:10px auto;overflow:hidden;border:1px solid green;}
.menu li{position:relative;padding-left:4px;height:22px;line-height:22px;/*此属性相当重要啊,没了它,下划线就木有了,原理你懂的*/white-space:nowrap;font-size:14px;/*此后的设置针对ie6,子元素设置为position:relative;时,在Ie6中找不到父元素*/width:100%;overflow:hidden;}
.menu li .page_index{position:absolute;display:block;padding:0 4px;right:0;top:0;line-height:22px;z-index:1;background:#fff;}
.menu li .dashed_line{height:0;overflow:hidden;display:inline-block;width:100%;margin:0 4px;border-bottom:1px dashed #333;/*实现下划线居中*/vertical-align:middle;}

html结构:

IE9中的“浏览器模式”和“文档模式”

浏览器模式”和“文档模式”的区别 在IE8中按F12键,打开“开发人员工具”,在菜单栏中可以看到“浏览器模式”和“文档模式”的切换菜单,其中可以选择切换到IE6/7/8等不同的网页模式。那“浏览器模式”和“文档模式”之间有什么区别呢? “浏览器模式”用于切换IE针对该网页的默认文档模式、对不同版本浏览器的条件备注解析、发送给网站服务器的用户代理(User-Agent)字符串的值。网站可以根据浏览器返回的不同用户代理字符串判断浏览器的版本和安装的功能,这样就可以向不同的浏览器返回不同的页面内容。 默认情况下,IE8的浏览器模式为IE8。用户可以通过单击地址栏旁边的兼容性视图按钮( )来手动切换到不同的浏览器模式。在IE8中,IE8兼容性视图会以IE7文档模式来显示网页,同时会向服务器发送IE7的用户代理字符串。 “文档模式”用于指定IE的页面排版引擎(Trident)以哪个版本的方式来解析并渲染网页代码。切换文档模式会导致网页被刷新,但不会更改用户代理字符串中的版本号,也不会从服务器重新下载网页。切换浏览器模式的同时,浏览器也会自动切换到相应的文档模式。

IE9中的“浏览器模式”和“文档模式”
IE9中的“浏览器模式”和“文档模式”
IE9中的“浏览器模式”和“文档模式”

Web设计(UI/UE)经验的总结

人们通常在访问购物网站时,并未将它当作艺术品来赞赏。而是为了获得有关产品的信息,找到他想要的产品。所以网站的设计应该尽量清楚和有条理,以便他们能够容易的找到想要购买的产品。

在进行Web设计时,形式应该服从功能。这种方法应用于我们站点的整个设计过程中。

基本设计中注意的几处:

1、用户界面元素要一致.同一个控件在不同的页面上功能要相同。

2、导航栏位置要一致。决定站点的哪些页和功能需要在站点的任何页上都可被访问到。这就是应该保持一致性的”全局导航栏”。

3、注意基本的图形设计原则:例如排版式样、色彩和版面的设计。

4、注意相关元素和功能模块的位置和目的,这可帮助访问者从其它相邻的选择和位置来推断某个链接的功能。

5、网页不可以过于庞大,图片需要使用适当的压缩模式来优化它们。

设计中的难点、矛盾,也是规则:

1、我们要将站点设计得尽量简单易用。

2、另一方面,我们要确保站点中所有强大的工具可为经验丰富的用户所用。

做以下的工作:

1、了解您的用户,调查究竟哪些人在访问您的站点,以及他们为什么要访问。

2、为您的用户提供所需的信息。使导航元素保持一致,并且确保对访问率最高的区域进行明显的标记,是它们易于被找到。

3、使用清楚的消息,如果您需要用户填写姓名,那么就直截了当地说。让访问者自己去计算,他们会感到沮丧,于是转到其它更简单的站点。

4、保持一致性,虽然更改不同Web页的外观并不难,但这并不意味着您应该这么做。将主要功能–例如返回”主页”的链接或者执行一个搜索–放在每页的相同位置。

5、使站点可用。牢记设计和测试站点的可用性。确保用户可容易地执行任务以获得所需信息。如果新的设计没有在这些方面获得改善,那么就不要实施它。

6、保持简洁,说起来容易做起来难。尝试征求反馈意见。有时新人可以很容易找到解决方案。

7、尝试新的东西.不要害怕打破常规,尝试一些完全不同的东西。如果您不试试,永远不会找到真正的答案。

CMake 手册详解目录

 

 

 

8、configure_file

9、CMake手册详解 (九)内容为else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile
execute_process export

10、file< 文件操作命令

11、find_file<查找一个文件的完整路径。

12、find_library<查找一个库文件

13、find_package 为外部工程加载设置。

14、find_path<搜索包含某个文件的路径

15、find_program 查找可执行程序

16 、CMake 手册详解(十六)foreach  function  get_cmake_property  get_directory_property  get_filename_component

 

在一个千万级的数据库查寻中,如何提高查询效率?分别说出在数据库设计、SQL语句、java等层面的解决方案。

在一个千万级的数据库查寻中,如何提高查询效率?分别说出在数据库设计、SQL语句、java等层面的解决方案。
解答:
1)数据库设计方面:
a. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
b. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0
c. 并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
d. 索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
e. 应尽可能的避免更新索引数据列,因为索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新索引数据列,那么需要考虑是否应将该索引建为索引。
f. 尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
g. 尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
h. 尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
i. 避免频繁创建和删除临时表,以减少系统表资源的消耗。
j. 临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
k. 在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
l. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
2)SQL语句方面:
a. 应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
b. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20 可以这样查询: select id from t where num=10 union all select id from t where num=20
c. in 和 not in 也要慎用,否则会导致全表扫描,如: select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了: select id from t where num between 1 and 3
d. 下面的查询也将导致全表扫描: select id from t where name like ‘%abc%’
e. 如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t wherenum=@num 可以改为强制查询使用索引: select id from t with(index(索引名)) wherenum=@num
f. 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where num/2=100 应改为: select id from t where num=100*2
g. 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where substring(name,1,3)=’abc’–name以abc开头的id select id from t where datediff(day,createdate,’2005-11-30′)=0–‘2005-11-30’生成的id 应改为: select id from t where name like ‘abc%’ select id from t where createdate>=’2005-11-30′ and createdate<‘2005-12-1’
h. 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
i. 不要写一些没有意义的查询,如需要生成一个空表结构: select col1,col2 into #t from t where 1=0 这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样: create table #t(…)
j. 很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num)
k. 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
l. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
m. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
n. 尽量避免大事务操作,提高系统并发能力。
3)java方面:
a.尽可能的少造对象。
b.合理摆正系统设计的位置。大量数据操作,和少量数据操作一定是分开的。大量的数据操作,肯定不是ORM框架搞定的。,
c.使用jDBC链接数据库操作数据
d.控制好内存,让数据流起来,而不是全部读到内存再处理,而是边读取边处理;
e.合理利用内存,有的数据要缓存

AR眼镜将改变我们的世界

什么是AR

AR其实是Augmented Reality的缩写,中文叫增强现实。最近两年因为移动设备和定位技术的普及,AR也逐渐热了起来。

所谓增强现实,就是在你看到的现实世界中添加物体的技术。听起来很炫,但其实现却弱爆了——因为它要求你通过摄像头去看世界。技术原理很简单,计算机在显示从摄像头捕捉到的图像的同时,再叠加上额外的附加图像就OK。 为了让叠加上去的物体更加真实,一般会让这个物体随着摄像头视角的移动而改变,从而看起来像真的一样。

要做到这样,要准备两个东西,一个是建立好的3D模型,一个是实时获取的视角变换数据。为了更容易算出视角变幻,一般会要求在摄像头前放置一个有特殊标示的纸片用于定位。 OK,我们看看看这个技术能给动漫宅网友带来什么福利。

通过AR技术,技术宅们将初音的3D模型投射到了现实的桌面上,从而可以通过摄像头360°的欣赏甩葱动作。 当然游戏厂商也不例外,制作国民女友的《LovePlus》在其发布的iPhone应用中也加入了AR技术,只要将标志打印出来,贴到地板、椅子或者桌子上,就能通过iPhone的摄像头看到自己在游戏里的女朋友啦。

没玩过的同学可以去这里下载

当AR遇到GoogleGlasses

为什么这么NB的技术一直没能规模化流行呢?有几个原因。

首先是摄像头的问题。只能通过摄像头观看这个特点严重的制约了AR的使用,在没有智能手机的年代,谁都不会随时带个摄像头在身边。到了智能手机一统天下的时候,摄像头对电量的消耗又让人不可能随时开启,这使AR构造起来的代入感不能够持续。

然后是标记定位也存在问题。需要打印标记才能定位很不方便,不过近期一些图像识别技术已经可以直接通过像素捕捉对比来做粗略的定位了。

还有手机性能也是问题,从08年开始我就持续关注这个技术,但大概到iPhone3G的时候,开源的AR库才能够流畅的运行。

所以当我看到Google Glasses的时候,我知道AR的时代真正来临了。Google Glasses本身是眼镜,这让它不用通过摄像头去显示现实,而在光线进入人眼前,却可以进行修改和叠加。这完美的解决了AR体验持续化的问题。

Google Glasses还提供了定位数据,通过GPS、加速器和气压计,我们可以很精确的描述一个人在现实世界的位置,然后将一个虚拟的世界叠加进来。这将从根本上改变我们的交互方式。

在游戏领域,这意味着一个以真实世界为基础的虚拟世界将被激活,以往只在家里活动的游戏宅们,将在现实中相聚、相识和协作。如果你无法想象,那么来看看Google发布的这款AR游戏——ingress

目前这款游戏还只是在手机上使用,当我相信一旦Google Glasses正式发布,它将随之发布真正震撼的版本。

到那个时候,只存在于童话、电影、小说和二次元里边的平行世界将被建立。我们看见的那个现实,将被一副眼镜彻底改变。