websocket服务端开发
基于http请求以拉的方式去做服务器的推送,无论是实时性和有效字节都是差强人意的效果。
公司的im系统在与客户端的交互上实际上借助了websocket来实现服务器与客户端的事实消息推送,今天就来简单了解下这个协议,并且自己实现对websocket的响应。

可以看到在理解了tcp和http之后,websocket的设计其实并不复杂,再最开始建立链接的时候客户端实际上会进行一次http请求,只不过请求头的内容有些特别,这里我们来看下:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protool: chat,superchat
Sec-WebSocket-Version:13
可以看到这个报文里包含了一些附加头信息。其中附加头信息"Upgrade: WebSocket" ,表明这是一个申请协议升级的http请求。"Sec-WebSocket-Key"是随机的,服务端会用这些数据构造出
一个SHA-1的信息摘要,把"Sec-WebSocket-Key"加上一个魔幻字符串"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"。使用SHA-1加密,然后进行BASE-64编码,将结果作为"Sec-WebSocket-Accept"头的值,返回给客户端:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protool: chat
实现对websocket请求的响应:
public class WebsocketServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(8080);
Socket socket= serverSocket.accept();
new Thread(new Handle(socket)).start();
}
}
public class Handle implements Runnable{
private Socket socket;
Handle(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
OutputStreamWriter streamWriter=new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bufferedWriter=new BufferedWriter(streamWriter);
String key=null;
//读报文
while (true){
String s= reader.readLine();
System.out.println(s);
if (s.equals("")){
break;
}else{
if (s.contains("Sec-WebSocket-Key")){
String keyValue[]=s.split(":");
key=keyValue[1].trim()+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
}
}
}
//写报文
MessageDigest messageDigest=DigestUtils.getSha1Digest();
byte[] digest=messageDigest.digest(key.getBytes());
Base64 base64 = new Base64();
String finalKey=base64.encodeToString(digest);
bufferedWriter.write("HTTP/1.1 101 Switching Protocols\r\n");
bufferedWriter.write("Upgrade: websocket\r\n");
bufferedWriter.write("Connection: Upgrade\r\n");
bufferedWriter.write("Sec-WebSocket-Accept: "+finalKey+"\r\n");
bufferedWriter.write("Sec-WebSocket-Protool: chat\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.write("test");
bufferedWriter.write("\r\n");
bufferedWriter.flush();
//接收数据
System.out.println("响应报文已经发送");
while (true){
String s=reader.readLine();
System.out.println(s==null);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
建立连接的时候要注意 Sec-WebSocket-Key在做sha-1哈希时,取得时摘要 然后拿着摘要去做base64遍嘛得到Sec-WebSocket-Accept,上面代码还有问题就是连接建立之后 BufferedReader的readLine()方法在遇到\r,\r\n,\n之前会等到填满缓冲区才会被唤醒,找的很多测试用的客户端都会把换行符去掉导致线程在填满缓冲区8KB之前一直阻塞,另一个问题就是字符流的编码问题。这里更多的关注连接建立过程,连接建立之后其实就是直接用tcp传输数据了,这里不多做赘述
websocket服务端开发的更多相关文章
- 用nodejs快速实现websocket服务端(带SSL证书生成)
有不少公司将nodejs的socket.io作为websocket的解决方案,很遗憾的是socket.io是对websocket的封装,并不支持html5原始的websocket协议,微信小程序使用的 ...
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...
- 在线教学、视频会议 Webus Fox(2) 服务端开发手册
上次在<在线教学.视频会议软件 Webus Fox(1)文本.语音.视频聊天及电子白板基本用法>里介绍了软件的基本用法.本文主要介绍服务器端如何配置.开发. 1. 配置 1.1 IIS配置 ...
- C# WebSocket 服务端示例代码 + HTML5客户端示例代码
WebSocket服务端 C#示例代码 using System; using System.Collections.Generic; using System.Linq; using System. ...
- Android 服务端开发之开发环境配置
Android 服务端开发之开发环境配置 这里是在Eclipse的基础上安装PhpEclipse插件方法,PHPEclipse是Eclipse的 一个用于开发PHP的插件.当然也可以采用Java开发a ...
- nodejs服务端开发学习笔记
正在学习中,不断改错... 学习了一段时间nodejs,对其中的很多东西还不是很理解,在网上看过很多的例子,希望通过自己的一些总结让自己了解的更全面些,同时也作为学习笔记留存备忘. 准备工作 node ...
- Swift3.0服务端开发(三) Mustache页面模板与日志记录
本篇博客主要介绍如果在Perfect工程中引入和使用Mustache页面模板与日志记录系统.Mustache页面模板类似于PHP中的smarty模板引擎或者Java中的JSTL标签.当然Mustach ...
- Swift3.0服务端开发(五) 记事本的开发(iOS端+服务端)
前边以及陆陆续续的介绍了使用Swift3.0开发的服务端应用程序的Perfect框架.本篇博客就做一个阶段性的总结,做一个完整的实例,其实这个实例在<Swift3.0服务端开发(一)>这篇 ...
- 如何有效快速提高Java服务端开发人员的技术水平?
我相信很多工作了3-5年的开发人员都会经常问自己几个问题: 1.为什么总是感觉技术没有质的提高? 2.如何能够有效和快速的提高自身的技术水平? 3.如何进入到一个牛逼的大公司,认识牛逼的人? 这篇文章 ...
随机推荐
- for循环中的let与var的说明
参考资料:<JavaScript高级程序设计> 在 let 出现之前,for 循环定义的迭代变量会渗透到循环体外部: for (var i = 0; i < 5; ++i) { ...
- Java Arrays 和 List的相互转化
最近在 leetcode 刷题的时候遇到过好几次这样的情况:需要返回的数据类型是数组(Arrays),但是求解的时候并不知道数组的长度,这时候就需要先用 List 进行临时存储,最后再转化为 Arra ...
- Java学习的第五天
1.值域转化的规则:值域小的类型可以自动转化成值域大的类型,值域大的类型可以强行转化成值域小的类型,但要注意精度,除了基本类型可以转换,引用类型之间也可以转换. 引用类型可以是类,借口,数组. 常见的 ...
- python机器学习的开发流程
标准机器学习的开发编程流程 关注公众号"轻松学编程"了解更多. 一.流程 标准机器学习的开发编程流程: 1.获取数据(爬虫.数据加载.业务部门获取) 2.数据建模(摘选样本数据(特 ...
- 较详细的gdb入门教程
本文主要介绍gdb的基础使用.若需了解一些技巧,请访问此篇博客:点这里 本篇教程适用于Windows,macOS及Linux,但由于Windows的自带终端很难用,所以体验可能不太好.Windows ...
- 3、编程语言与Python介绍
一 引子 基于上一章所学,有了计算机硬件,再在硬件之上安装好操作系统,我们就有了一个应用程序的运行平台,我们接下来的任务就是学习如何使用某款编程语言来开发应用程序. 本章的主题是先了解一下编程语言,然 ...
- .NET 5 和 C#9 /F#5 一起到来, 向实现 .NET 统一迈出了一大步
经过一年多的开发,Microsoft 于北京时间 11 月 11 日(星期三)发布了其 .NET 5软件开发平台,强调平台的统一,并引入了 C# 9 和 F# 5 编程语言,新平台朝着桌面.Web.移 ...
- 腾讯云对象存储COS新品发布——智能分层存储,自动优化您的存储成本
近日,腾讯云正式发布对象存储新品--智能分层存储,能够根据用户数据的访问模式,自动地转换数据的冷热层级,为用户提供与标准存储一致的低延迟和高吞吐的产品体验,同时具有更低的存储成本. 熟悉数据存储的用户 ...
- JS基础算法题(二)
1.1 数组去重的五种方法 数组去重:将数组中重复的元素去掉 JS数组没有删除具体元素的删除(只能删掉值,删不掉元素的索引),可以使用另外一个结构来进行存储 新数组 新对象 JS数组虽然本质可以删除第 ...
- 《GNU_Makefile》——第3章,Makefile总述
1.makefile的内容 一个完整的makefile包含5个东西: 显示规则,隐含规则,变量定义,指示符,注释 (1)显示规则 描述如何更新目标文件. (2)隐含规则 make程序内置的规则. ma ...