现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP request的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。

Ajax轮询——“定时的通过Ajax查询服务端"

而比较新的技术去做轮询的效果是Comet,使用了AJAX。但这种技术虽然可达到双向通信,但依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源。

Comet——随着AJAX技术兴起而产生的新技术

用大白话揭开Ajax长轮询(long polling)的神秘面纱

面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。

国际惯例,先上维基百科的解释。

"WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。"

——维基百科

上面是维基百科对WebSocket的解释,别问我如何解释上面这段话,因为我也没看懂,那么下面我用人话解释一下吧(仅仅是我的理解):

WebSocket是一个协议,可以简单看成是HTTP协议的一个补充协议,WebSocket借助HTTP协议的基础完成服务器主动与客户端实时传输数据。

这是WebSocket和HTTP之间的关系,有交集,但是并不是全部。

WebSocket只是HTML5其中的一个API(HTML5推出了很多新的API,赞),这个API可以通过WebSocket协议实现WebSocket技术。

在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

关键点在于如何"握手",只要我们完成了握手的这个工作,那么WebScoket技术就算是能够使用了。

前面说了WebSocket与HTTP有交集的,或者可以说WebSocket借助了HTTP的基础就是体现在这里了,可以看到图中的红点,分别是WebSocket的请求头和响应头,一来一回,握手也就完成了,实时连接也就建立起来了!

下面讲解一下几个重要的头参数:

Request:

Upgrade:WebSocket; //指定WebSocket协议

Sec-WebSocket-Version: 13 //指定Websocket Draft协议版本

Sec-WebSocket-Key:Cv8RLRCr07Ujlqexqq9Nrw== //验证key值,由浏览器随机生成,可以理解为一个校验码

Reponse:

Connection:Upgrade ; Upgrade:webSocket;//没错我就是webSocket

Sec-WebSocket-Accept:rC+mM80welcslAqBHpav4MSDzAU= ;//这是返回头校验码,和请求头的Key配对

Sec-WebSocket-Version: 13 //指定Websocket Draft协议版本

以上就是一次完成的WebSocket握手,握手完之后就可以进行实时通信了。

先上个代码看看:

本文所用服务端语言为PHP,其他语言可以对照着看,大的原理都一样:

WebSocket Demo下载链接(代码实在太长,直接下载吧)

使用方法

Windows下要用cmd启动server.php文件,Linux同理
然后用浏览器访问index.html
Demo是上网找的,不能当做实际用途,简单看看运行流程就好

代码需要改的就是index.html的url和server.php的ip。

我讲解几个重要的模块

server.php:

  <?php

    include 'websocket.class.php';

    $config=array(

    'address'=>'127.0.0.1',

    'port'=>'8000',

    'event'=>'WSevent',//回调函数的函数名

    'log'=>true,

    );

    $websocket = new websocket($config);

    $websocket->run();

server.php:通过cmd运行server.php,引用并实例化websocket.class.php类库,并执行run方法,使其充当一个"服务器",持续挂着这个连接,当客户端有消息就做出对应动作。

Index.html:

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>websocket_TEST</title>

<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>

</head>

<body>

<textarea class="log" style="width: 100%; height: 500px;">

=======websocket======

</textarea>

<input type="button" value="连接" onClick="link()">

<input type="button" value="断开" onClick="dis()">

<input type="text" id="text">

<input type="button" value="发送" onClick="send()">

<script>

function link(){

var url='ws://127.0.0.1:8000';

socket=new WebSocket(url);

socket.onopen=function(){log('连接成功')}

socket.onmessage=function(msg){log('获得消息:'+msg.data);console.log(msg);}

socket.onclose=function(){log('断开连接')}

}

function dis(){

socket.close();

socket=null;

}

function log(var1){

$('.log').append(var1+"\r\n");

}

function send(){

socket.send($('#text').attr('value'));

}

function send2(){

var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')})

socket.send(json);

}

</script>

</body>

</html>

Index.html:HTML5提供了WebSocket API,所以,客户端实例化此API,参数为IP:端口,连接上服务端的WebSocket连接。

function roboot()

<?

function roboot($sign,$t){

global $websocket;

switch ($t)

{

case 'hello':

$show='hello,GIt @ OSC';

break;

case 'name':

$show='Robot';

break;

case 'time':

$show='当前时间:'.date('Y-m-d H:i:s');

break;

case '再见':

$show='( ^_^ )/~~拜拜';

$websocket->write($sign,'Robot:'.$show);

$websocket->close($sign);

return;

break;

case '天王盖地虎':

$array = array('小鸡炖蘑菇','宝塔震河妖','粒粒皆辛苦');

$show = $array[rand(0,2)];

break;

default:

$show='( ⊙o⊙?)不懂,你可以尝试说:hello,name,time,再见,天王盖地虎.';

}

$websocket->write($sign,'Robot:'.$show);

}

function roboot():指定了客户端的操作和服务端回复的信息,客户端发送' 天王盖地虎',服务端返回信息' 小鸡炖蘑菇'/' 宝塔震河妖'/' 粒粒皆辛苦'。

文章最后来个小科普:

关于Socket 与 WebScoket

Socket 其实并不是一个协议。它工作在 OSI 模型会话层(第5层),是为了方便大家直接使用更底层协议(一般是 TCP 或 UDP )而存在的一个抽象层。

最早的一套 Socket API 是 Berkeley sockets ,采用 C 语言实现。它是 Socket 的事实标准,POSIX sockets 是基于它构建的,多种编程语言都遵循这套 API,在 JAVA、Python 中都能看到这套 API 的影子。

下面摘录一段更容易理解的文字(来自 http和socket之长连接和短连接区别):

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

主机 A 的应用程序要能和主机 B 的应用程序通信,必须通过 Socket 建立连接,而建立 Socket 连接必须需要底层 TCP/IP 协议来建立 TCP 连接。建立 TCP 连接需要底层 IP 协议来寻址网络中的主机。我们知道网络层使用的 IP 协议可以帮助我们根据 IP 地址来找到目标主机,但是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通信就要通过 TCP 或 UPD 的地址也就是端口号来指定。这样就可以通过一个 Socket 实例唯一代表一个主机上的一个应用程序的通信链路了。

而 WebSocket 则不同,它是一个完整的 应用层协议,包含一套标准的 API 。

所以,从使用上来说,WebSocket 更易用,而 Socket 更灵活。

再简单来说, Socket是一个应用程序接口,是抽象的,WebSocket和HTTP是具体实现,

参考文章:

https://www.zhihu.com/question/20215561 《 知乎回答:什么是WebSocket?》

https://zh.wikipedia.org/wiki/WebSocket 《维基百科:WebSocket》

http://zengrong.net/post/2199.htm 《zrong's blog》

原文:
https://segmentfault.com/a/1190000005041671

简单又好用的聊天室技术——WebSocket的更多相关文章

  1. JavaWeb网页聊天室(WebSocket即时通讯)

    原文:http://baike.xsoftlab.net/view/656.html Git地址 http://git.oschina.net/loopcc/WebSocketChat 概要: Web ...

  2. 打造属于你的聊天室(WebSocket)

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  3. 通过实现简单聊天室了解websocket的基础使用

    websocket基础使用 用到的依赖包 websocket的依赖 <dependency> <groupId>javax.websocket</groupId> ...

  4. 学习WebSocket(二):使用Spring WebSocket做一个简单聊天室

    聊天室高频率.低延时完全符合websocket的特点,所以聊天室使用websocket再适合不过了. 聊天室的功能并没有比上一节代码多多少,主要在握手阶段对用户的session做处理,对用户的消息进行 ...

  5. Vue开发多人聊天室 复盘总结

    前言 在上个月初,接到一个需求,要开发一个 聊天通讯 模块 并且 集成到 项目中的多个 入口,实现业务数据的记录追踪. 接到需求后,还挺开心,这是我第一次 搞 通讯 类的需求,之前一直是 B 端 的业 ...

  6. JAVA-Socket通信 打造属于自己的聊天室(服务端)

    我们每天都在使用着微信.QQ等聊天软件,但不知你是否有想过这些聊天软件是如何实现的?是否想过要制作一个属于自己的聊天室? 本篇博客将带你打造一个简单的属于自己的聊天室,将cmd作为聊天窗口,可通过内网 ...

  7. 基于WebSocket实现网页版聊天室

    WebSocket ,HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,其使用简单,应用场景也广泛,不同开发语言都用种类繁多的实现,仅Java体系中,Tomcat,Jetty,Sp ...

  8. 手动搭建I/O网络通信框架3:NIO编程模型,升级改造聊天室

    第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 第二章:手动搭建I/O网络通信框架2:BIO编程模型实现群聊 在第二章中用BIO编程模型,简单的实现了一 ...

  9. python tornado websocket 多聊天室(返回消息给部分连接者)

    python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端! chatHome.py // 服务器端, 渲染主页 --> 聊天室建立web ...

随机推荐

  1. DBA_实践指南系列4_Oracle Erp R12系统备份和恢复Backup(案例)

    2013-12-04 Created By BaoXinjian

  2. setContentView(R.layout.activity_main)无法正常引用

    今天在写Android代码的过程中,编译器一直报错,错误出在这一行代码: setContentView(R.layout.activity_main) 提示信息是: activity_main can ...

  3. Python 列表 remove() 方法

    描述 Python 列表 remove() 方法通过指定元素的值来移除列表中某个元素的第一个匹配项,如果这个元素不在列表中会报一个异常. 语法 remove() 方法语法: L.remove(obj) ...

  4. struts2.xml中所有constant详解--大全

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-/ ...

  5. react dva 的 connect 与 @connect

    https://dvajs.com/guide/introduce-class.html#connect-方法 connect的作用是将组件和models结合在一起.将models中的state绑定到 ...

  6. Leaf——美团点评分布式ID生成系统

    背景 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数 ...

  7. Securecrt emacs/vi 代码无法高亮、无颜色

    无法高亮: 这是因为.bashrc中没有 export term=linux 最后,代码恢复正常:

  8. Python中的break和continue的使用方法

    一.continue的使用方法(结束当前的循序,进行下一个数的循环) # *************************************************************** ...

  9. OOM问题定位方法

    1. 背景 线上内存OOM问题是最难定位的问题,最常见的原因: (1)本身资源不够 (2)申请的太多 (3)资源耗尽 某服务器上部署了Java服务,出现OutOfMemoryError,请问有可能是什 ...

  10. angular -- $route API翻译

    $route -$routeProvider服务 -依赖ngRoute模块 $route能够在路径发生改变的时候,渲染不同的视图,调用不同的控制器.它监测了$location.url(),然后根据路径 ...