前言:
  大家刚学socket编程的时候, 往往以聊天室作为学习DEMO, 实现简单且上手容易. 该Demo被不同语言实现和演绎, 网上相关资料亦不胜枚举. 以至于很多技术书籍在讲解网络相关的编程时, 不再采用聊天室做为基础案列, 而采用其他案例. 比如之前火热一时的"你猜我画", 以避免显得很大众.
  但说实话, 几乎所有的网络程序追踪溯源, 都可以从聊天室中找到影子. 在线聊天室也不局限于简单的单机服务, 其分布式实现技术含量十足. 犹如达芬奇画鸡蛋, 中间虽枯燥, 但坚持不懈, 精益求精. 终于水滴石穿, 从量变到质变.
  本章将讲讲, websocket的协议和javascript版的API.

websocket协议:
  websocket基于tcp的双向通讯协议. 其协议可以分为两个部分, 握手数据传输. 其握手协议构建于http/https, 而数据传输协议则脱离于http/https.
  websocket协议历经了很多版本的修改和升级, 字段和约定的差异, 使得编码时需要注意版本的兼容性. 当前使用最普遍的是版本13.
  其协议uri可以表示为"ws://{host}:{port}/{path}", 在ssl/tls下是"wss://{host}:{port}/{path}".
  • 握手协议
  在该阶段, 其交换为request/response的方式进行.

  
  如简单的例子为案例, 其http请求头中包含如下的字段:
  
  Connection: Upgrade
  Upgrade: websocket
  Sec-WebSocket-Key: A2mIDkRXEgl0+79uPwhsOw==
  Sec-WebSocket-Version: 13
  服务端通过识别header中的Upgrade:websocket字段来区分正常的http请求还是websocket协议.
  而Sec-WebSocket-Key则是客户端生成的一个随机key, 用于和服务端进行的验证工作.
  服务端的响应如下所示:
  
  Sec-WebSocket-Accept: hQCy41pGdjZ222NKXfyrxQUHZEQ=
  其http响应码为101, Sec-WebSocket-Accept为服务端对应于客户端Sec-WebSocket-Key的验证值.
  其具体的算法, 可以描述如下:

${Sec-WebSocket-Accept}=base64(sha1(${Sec-WebSocket-Key}+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

  • 数据协议
  在该阶段, 客户端和服务器其数据交换格式, 就约定为Frame模式了. 一般一条消息为一个frame, 当然一个消息可以由多个frame组成. 这样的好处, 就像http的chunk模式一样, 一边生成一边传输.
  Frame具体的定义如下所示:
  
  每个字段都有其具体的含义, 这边就不再具体的展开了.
  其Frame的分类可以大致如下:
  
  Ping/Pong Frame由应用层协议本身完成, 这样基于websocket开发的网络应用服务, 就可以少去了死链检测/重连这一环节了.
  Text Frame往往用的比较多, 也有使用Binary Frame的, 比如基于websocket实现的MQTT服务.
  Connection Close Frame是一种友好协商断掉连接的一种方式.

Javascript版API:
  WebSocket其对应的javascript代码如下:

// *) websocket链接本身的状态
WebSocket.CONNECTING = 0;
WebSocket.OPEN = 1;
WebSocket.CLOSING = 2;
WebSocket.CLOSED = 3; // *) websocket实体对象的成员
WebSocket.prototype.url = null;
WebSocket.prototype.readyState = 0;
WebSocket.prototype.bufferedAmount = 0;
WebSocket.prototype.extensions = null;
WebSocket.prototype.protocol = null; // *) websocket实体对应的回调函数, 需要被继承实现
WebSocket.prototype.onopen = 0;
WebSocket.prototype.onmessage = 0;
WebSocket.prototype.onerror = 0;
WebSocket.prototype.onclose = 0; // *) websocket实体的send/close方法
function WebSocket(url,protocols) {}
WebSocket.prototype.send = function(data) {};
WebSocket.prototype.close = function(code,reason) {};

  主要还是websocket对应的回调函数实现, 当然也需知道websocket本身所处的状态.

总结:
  该篇博文有堆砌之感, 但如果你想实现一个基于websocket实现的聊天室, 对其内部的协议和流程需要有个清晰的了解. 特别是之后的基于Netty开发的服务器, 虽然可以照猫画虎, 但知其然不知其所以然.
  本文参考了websocket的wiki, 以及rfc说明.

写在最后:
  
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

  

在线聊天室的实现(1)--websocket协议和javascript版的api的更多相关文章

  1. 在线聊天室的实现(2)--基于Netty 4.x的Echo服务器实现

    前言: 就如前文所讲述的, 聊天室往往是最基本的网络编程的学习案例. 本文以WebSocket为底层协议, 实现一个简单的基于web客户端的Echo服务. 服务器采用Netty 4.x来实现, 源于其 ...

  2. 使用WebSocket实现简单的在线聊天室

    前言:我自已在网上找好了好多 WebSocket 制作 在线聊天室的案列,发现大佬们写得太高深了 我这种新手看不懂,所以就自已尝试写了一个在线简易聊天室 (我只用了js 可以用jq ) 话不多说,直接 ...

  3. 基于Server-Sent Event的简单在线聊天室

    Web即时通信 所谓Web即时通信,就是说我们可以通过一种机制在网页上立即通知用户一件事情的发生,是不需要用户刷新网页的.Web即时通信的用途有很多,比如实时聊天,即时推送等.如当我们在登陆浏览知乎时 ...

  4. 百度前端面试题-类似slack的在线聊天室

    别人国庆出去玩,我在家写代码的感觉也是很不错哒. 首先介绍一下技术架构吧! 使用了js框架:FFF,zepto,jquery,md5.min.js 前端框架:Bootstrap 后端:野狗,部分PHP ...

  5. swoole中websoket创建在线聊天室(php)

    swoole中websoket创建在线聊天室(php) swoole现仅支持Linix,macos 创建websocket服务器 首先现在服务器创建一个websocket服务器 <?php // ...

  6. Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)

    简单介绍 关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) 在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现 ...

  7. 三、jQuery--jQuery基础--jQuery基础课程--第12章 jQuery在线聊天室

    在线聊天室案例 一.功能简介: 1.用户需要登录后才能进入聊天室交流 2.已无刷新的方式,动态展示交流后的内容和在线人员的基本信息 3.登录后的用户可以提交文字和表情图标 技术重点:利用ajax的无刷 ...

  8. 基于JQuery+JSP的无数据库无刷新多人在线聊天室

    JQuery是一款非常强大的javascript插件,本文就针对Ajax前台和JSP后台来实现一个无刷新的多人在线聊天室,该实现的数据全部存储在服务端内存里,没有用到数据库,本文会提供所有源程序,需要 ...

  9. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

随机推荐

  1. Spring 定时任务2

    转载自http://www.cnblogs.com/nick-huang/p/4864737.html > 版本说明 <dependencies> <dependency> ...

  2. Linux 执行ll命令时指定按文件时间或大小排序

    按时间排序: $ ll -ht 按大小排序: $ ll -hS 使用--help查看命令的用法,如 $ ll --help

  3. 特征的Attribute Only选项

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  4. C++用PostMessage模拟按钮点击

    有时我们可能会在某个程序中用到模拟按钮点击事件. 本文中的例子在MFC程序中调试通过,duilib的没试过,还需探索 不多说,上代码: #include "stdafx.h" #i ...

  5. [Oracle] SQL*Loader 详细使用教程(1)- 总览

    SQL*Loader原理   SQL*Loader是Oracle提供的用于数据加载的一种工具,它比较适合业务分析类型数据库(数据仓库),能处理多种格式的平面文件,批量数据装载比传统的数据插入效率更高. ...

  6. window svn链接

    我学会怎么建立window SVN服务器了 今天,终于学会怎么自己搭建SVN服务了,以前一直用的都是公司的SVN服务,没接触过,觉得很神秘,曾经我一个同事弄了好几天,也没搭成,对我打击挺大的:( 觉得 ...

  7. 转json using指令

    using Newtonsoft.Json;using Newtonsoft.Json.Converters; string result = JsonConvert.SerializeObject( ...

  8. Android Studio编译输出apk文件修改文件名

    新建一个Android工程,默认编译会生成一个叫app-debug.apk或者叫app-release.apk文件,说实话,单纯看文件名,我都不到任何有用的信息,我希望输出的文件名是这样的: 模块名- ...

  9. (40) Aeroo 服务安装

    服务器 Odoo 8.0 操作系统: Ubuntu trusty14.04 说明:安装aeroo 要的要两个服务 areoo-docs 和 soffice 这里设定两个端口 8989 和 8100 = ...

  10. 学习笔记Jmail收发邮件

    一.利用Jmail发送邮件  1/// <summary> 2/// 利用Jmail发送邮件 3/// </summary> 4private void SendMailByJ ...