上一篇文章中使用了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. PCL关键点(1)

    关键点也称为兴趣点,它是2D图像或是3D点云或者曲面模型上,可以通过定义检测标准来获取的具有稳定性,区别性的点集,从技术上来说,关键点的数量相比于原始点云或图像的数据量减小很多,与局部特征描述子结合在 ...

  2. 《C++程序设计教程——给予Visual Studio 2008》读书笔记1,2章

    double *p1;       //p1为指向double型的指针变量 POINT *p2;       //p2为指向POINT型(点类型)的指针变量 int (*p3)[6];     //p ...

  3. 快速排序算法(Quicksort)

    快速排序算法是对集合中元素进行排序最通用的算法,俗称快排,其算法的时间复杂度为O(nlgn),空间复杂度为O(1). 我们举例来对其算法思路进行理解,譬如数组 A = { 4, 8, 1, 2, 9, ...

  4. 关于javascrpt if快速判断说明

    在js中有如下值能作为if的条件判断: 在js中有6种类型 undefined.null.string.number.boolean和object  object是对象类型 它们在逻辑运算符里有对应的 ...

  5. Python 文件操作一

    #-*- coding:utf-8 -*- #文件操作 #open()函数格式 #open(文件名,访问模式) f = open('1.md',"r") #read()没有不传参数 ...

  6. 6 ways to import data into SQL Server

    I’m going to go over some methods to import data from text files into SQL Server today. The particul ...

  7. SAP HR模块的基础数据表和增强配置

    信息类型是SAP HR模块数据单元,用于对人员数据的记录和维护,是HR的基础.信息类型按照其创建方式的不同可以分为:人事信息类型.组织信息类型.信息类型数据的维护主要在事物码PA30.PA40.po1 ...

  8. Linux C语言连接 sqlserver数据库

    记录一下Linux下使用C语言连接sqlserver的方法. 连接前需要安装freetds. 参考: http://www.cnblogs.com/helloworldtoyou/p/6910075. ...

  9. discuz 模板中如何使用方法和语言标签?

    第一个问题:如何调用方法? 关于模板中eval的使用{eval php 语句}比如:<!--{eval echo "Hello World!"}--> 工作中遇到一个小 ...

  10. Linux环境安装MySQL数据库(RPM格式的软件包)

    1.  下载mysql安装包 下载地址1:  http://www.mysql.com/   (mysql官网) 下载地址2:  http://mirrors.sohu.com/mysql/   (其 ...