上一篇文章中使用了Ajax long polling实现了一个简单的聊天程序,对于web实时通信,今天就来试用一下基于WebSocket的长连接方式。

WebSocket简介

为了增强web通信的功能,在HTML5中,提供了WebSocket,它不仅仅是一种web通信方式,也是一种应用层协议。

WebSocket提供了客户端和服务端之间的双全工跨域通信,通过客户端和服务端之间建立WebSocket连接(实际上是TCP连接,后面会看到),在同一时刻能够实现客户端到服务器和服务器到客户端的数据发送。

Ajax long polling是一种客户端去服务端拉取数据的方式,而WebSocket则能真正实现服务端主动向客户端推送数据。下图形象的展示了WebSocket的工作方式。

对于WebSocket这种新的应用层协议,在实现应用的时候,客户端和服务端都需要遵循WebSocket协议,关于更多的WebSocket内容,请参考websocket.org

实现

首先,还是先看看通过WebSocket实现的聊天程序的代码以及效果,然后再看WebSocket工作方式相关的内容。

客户端

因为并不是所有版本的浏览器都能够支持WebSocket,所以例子中通过下面代码来检测当前浏览器是否支持WebSocket。

if(window.WebSocket){
//support WebSocket, more code here
}
else{
alert("WebSocket was not supported");
}

对于客户端,主要就是updater这个对象,该对象会创建并维护了一个WebSocket对象,通过这个WebSocket对象就可以跟服务端进行交互(收取或发送消息)。

var updater = {
socket: null, start: function() {
var url = "ws://" + location.host + "/chatsocket";
updater.socket = new WebSocket(url); updater.socket.onopen = function(event) {
} updater.socket.onclose = function(event) {
alert("server socket closed");
} updater.socket.onmessage = function(event) {
updater.showMessage(event.data);
}
}, showMessage: function(message) {
console.log(message);
$("#inbox").append(message);
$("#message").val("");
}
};

服务端

对于服务端,这次使用了gevent-websocket这个库,可以很方便的通过pip进行安装。

服务端通过MessageBuffer这个类来管理所有的消息,以及所有的WebSocket client。由于WebSocket是一种长连接的方式,所以可以很容易的统计出当前在线的client的数量。

class MessageBuffer(object):
def __init__(self, cache_size = 200):
self.cache = []
self.cache_size = cache_size
self.clients = [] def new_message(self, msg):
self.cache.append(msg)
if len(self.cache) > self.cache_size:
self.cache = self.cache[-self.cache_size:] def update_clients(self, msg):
for client in self.clients:
client.send(msg)

跟上次相比,使用WebSocket之后,服务器代码更加简洁了。当客户端发起"/chatsocket"请求后,服务器就会跟客户端建立连接,并将客户端加入"messageBuffer.clients"列表中;当客户端断开连接,就会将客户端从"messageBuffer.clients"列表中移除。

当服务器收到新消息后,就会通过"messageBuffer.update_clients"方法,将新消息推送到所有的客户端。

def application(env, start_response):
# visit the main page
if env['PATH_INFO'] == '/':
# some code to load main page here elif env['PATH_INFO'] == '/chatsocket':
ws = env["wsgi.websocket"]
messageBuffer.clients.append(ws)
print "new client join, total client count %d" %len(messageBuffer.clients)
while True:
message = ws.receive()
if message is None:
messageBuffer.clients.remove(ws)
print "client leave, total client count %d" %len(messageBuffer.clients)
break
print "Got message: %s" %message
message = "<div>{0}</div>".format(message)
messageBuffer.new_message(message)
messageBuffer.update_clients(message)

运行效果

下面就是代码的运行效果。

由于WebSocket是长连接的方式,所以可以方便的统计当前在线客户端数量。

当关闭服务器的时候,客户端也可以检测到连接的断开。

WebSocket工作机制

下面就从工作机制来看看WebSocket是怎么为应用提供长连接服务的。

WebSocket连接建立

虽然WebSocket是一种新的应用层协议,但是它的工作也是要依赖于http协议的。

通过Wireshark,我们可以抓到下面的数据包。

这两个数据包就是建立WebSocket连接的握手过程(WebSocket Protocol handshake):

1. 客户端的WebSocket实例绑定一个需要连接到的服务器地址,当客户端连接服务端的时候,会向服务端发送一个类似下面的HTTP GET请求

在上面的请求中有一个Upgrade首部,这个首部是告诉服务端需要将通信协议切换到WebSocket

2. 在收到带有"Upgrade: websocket"首部的请求后,如果服务端支持WebSocket协议,那么它就会将自己的通信协议切换到WebSocket,同时发给客户端类似以下的响应报文头。

响应报文的状态码为101,表示同意客户端协议转换请求,并将它转换为WebSocket协议。到此,客户端和服务端的WebSocket连接就建立成功了,以后的通信就是基于WebSocket连接了。

WebSocket连接保活

WebSocket底层的工作/实现都是基于TCP协议,所以连接的保活机制是跟TCP一样的,就是通过"TCP Keep-Alive"心跳包来保证连接始终处于有效状态。

WebSocket连接关闭

对于WebSocket连接的关闭,也是主动关闭端发送"FIN, ACK"数据包来完成关闭的。

总结

本文简单介绍了HTML5中的WebSocket协议,并通过WebSocket实现了一个简单的聊天程序。

WebSocket能在客户端和服务端建立长连接,并提供全双工的数据传输,提供了服务器推送数据的模式。

跟Ajax long polling方式进行对比,这种服务器主动推送数据的方式更加适合实时数据交互应用。

Ps:

通过此处可以下载例子的源码。

初试WebSocket构建聊天程序的更多相关文章

  1. [转]使用 HTML5 WebSocket 构建实时 Web 应用

    HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例 ...

  2. 使用 HTML5 WebSocket 构建实时 Web 应用

    原文地址:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ HTML5 WebSocket 简介和实战演练 本文主要介绍 ...

  3. (转)使用 HTML5 WebSocket 构建实时 Web 应用

    HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例 ...

  4. WebSocket+Netty构建web聊天程序

    WebSocket 传统的浏览器和服务器之间的交互模式是基于请求/响应的模式,虽然可以使用js发送定时任务让浏览器在服务器中拉取但是弊端很明显,首先就是不等避免的延迟,其次就是频繁的请求,让服务器的压 ...

  5. websocket实现简单聊天程序

    程序的流程图: 主要代码: 服务端 app.js 先加载所需要的通信模块: var express = require('express'); var app = express(); var htt ...

  6. SpringBoot学习笔记(11):使用WebSocket构建交互式Web应用程序

    SpringBoot学习笔记(11):使用WebSocket构建交互式Web应用程序 快速开始 本指南将引导您完成创建“hello world”应用程序的过程,该应用程序在浏览器和服务器之间来回发送消 ...

  7. Node.js + Web Socket 打造即时聊天程序嗨聊

    前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术.像node.js这样的后端开拓者直接将前端人员的能力扩大到了后端.瞬间就有了一统天下的感觉,来往穿梭于前 ...

  8. 【转】iOS基于WebSocket的聊天机制

    原文网址:http://www.jianshu.com/p/21d9b3b94cfc WebSocket 的使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TC ...

  9. 基于 WebSocket 构建跨浏览器的实时应用

    Socket.IO – 基于 WebSocket 构建跨浏览器的实时应用 Socket.IO 是一个功能非常强大的框架,能够帮助你构建基于 WebSocket 的跨浏览器的实时应用.支持主流浏览器,多 ...

随机推荐

  1. SQLServer 错误: 15404,无法获取有关 Windows NT 组

    右击-属性-所有者改成sa 测试一下   右击 --- 作业开始步骤---执行成功

  2. asp.net无刷新上传(带预览)

    1.有个图片 <img id="Image1" title="用于广告栏及图文框缩略图" width="150" height=&qu ...

  3. 两个项目之间通过 RestTemplate 进行调用

    A服务发出请求: @RequestMapping("/jqgridjsondata.json") @ResponseBody public String jqgridJsonDat ...

  4. LDAP none、simple、strong 笔记

    // 该笔记仍在调研中!!不确保中有错误信息!最终目的是想用java实现这三种认证方式. 1.ldaps://  注意多了个s 参考:https://mail.python.org/pipermail ...

  5. 【转】性能测试,影响 TPS 的一些因素

    首先我们要先了解下TPS的具体含义: TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为单位. 下面 ...

  6. 自然语言交流系统 phxnet团队 创新实训 个人博客 (十一)

    名思义是 给游戏场景 添加一个 天空背景 让游戏更加精美,更具有魅力 添加天空盒 有两种方式  1 : 在当前相机上添加skybox   2 : 在当前场景上添加skybox 上面的两种方式的结果是一 ...

  7. Numpy 用于数组的文件输入和输出

    将数组以二进制格式保存 np.save 和np.load 是读写磁盘数组数据的两个主要函数.默认情况下,数组是以未压缩的原始二进制格式进行保持在扩展名 为.npy的文件中的 如果文件路径末尾没有扩展名 ...

  8. shell编程小结

    因为项目中要用到shell脚本,所以系统的看了一下.以前只是泛泛的了解. 变量:环境变量.预定义变量.位置变量.自定义变量. 环境变量这个好说,通过set或者env命令都能看到相应的列表,然后可以通过 ...

  9. Luhn算法检验和验证

    一.Luhn公式介绍 Luhn公式是一种广泛使用的系统,用于对标识号进行验证.它根据原始标识号,把每隔一个数字的值扩大一倍.然后把各个单独数字的值加在一起(如果扩大一倍后的值为2个数字,就把这两个数字 ...

  10. html5学习摘要

    1.HTML5简介 什么是 HTML5? HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML5 仍处于完善之中.然而,大部分现代浏览器已经具备了某些 HTML5 支 ...