webSocket的 原理 及 简单实现

websocket协议是基于Tcp的一种新的网络协议,它实现了客户端与服务器的双向通行,并允许服务端主动发送信息给客户端。WebSocket是html5中的协议。

Http协议与WebSocket协议:

Http协议只有1.0 和1.1 两个版本,

http协议是无状态的每一请求对应一个响应,而且响应完了就回结束连接,多个请求对应多个响应,每次都要重新建立连接。

在http1.1 中增加了 keep-alive (只是客户端的一种建议) ,用于在一个Http连接中,可以发送多个Request,接收多个Response。但依旧是每隔request对应一个response。

Connection:keep-alive

这个是通知服务器在 request/response 之后,不要理解断开tcp连接,后面的request/response 任然可以通过这个连接完成。但是这个只是个建议,服务端可能不支持,也可能时间长了,断开了连接。(通俗点就根服务端说下 ,后面可能还有事需要找你先不要挂了)

这个是不可能实现服务器主动push消息给客户端的。

那么如何能够实现呢?

But 我们可以使用ajax轮询 和long poll 技术,制造一个服务端push给客户端的假象。

那什么是Ajax轮询?

Ajax 轮询 就是隔几秒让浏览器发送请求询问服务端时候有消息了?

场景:

客户端:hi,有没有新信息(Request)
服务端:没有(Response)
客户端:hi,有没有新信息(Request)
服务端:没有。。(Response)
客户端:hi,有没有新信息(Request)
服务端:没有啊。。(Response)
客户端:hi有没有新消息(Request)
服务端:好了,有啦给你。(Response)
客户端:hi,有没有新消息(Request)
服务端:没有......

But 实际中这样会增加服务端的负载,降低服务端的效率。

什么是long poll 呢?

long poll 和ajax 轮询差不多,不过long poll 是阻塞的模式。也就是客户端发送一个request后 一直等待,知道服务端有消息response后才ok

场景:

客户端:hi,有没有新信息(Request)
服务端:没有(Response)
客户端:hi,有没有新信息(Request)
客户端:hi,有没有新信息(Request)

long pull 虽然降低了服务器的负载,但是需要服务器有很高的并发能力才可以。

ajax轮询、long poll技术虽然都能实现服务端消息的实时通知,但是各有缺点,都不是根本的解决办法。

既然他们都不行,那应该搞个新的协议。

WebSocket协议解决的客户端与服务端的双工通信的问题。

场景:

客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:13(HTTP Request)
服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:ok,有的时候会告诉你的。
服务端:发斯蒂芬
服务端:啊实打实大师
服务端:哈哈哈哈哈啊哈
服务端:笑死我了哈哈哈

  

request header

Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: Upgrade #通知服务器协议升级
Cookie: JSESSIONID=450BA8D626F785A1AE3BEB9AC9226CD0
Host: localhost:8099
Origin: http://localhost:8099
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: yjbBHsadoLeWtVNa+3Y2ow== #传输给服务器的key
Sec-WebSocket-Version: 13 #wesocket版本协议号13
Upgrade: websocket #协议升级为websocket协议
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Sec-WebSocket-Key 这个是客户端发送给服务端,服务端处理后再返回给客户端客户端进行验证 判断是否建立连接。
Connection: Upgrade #通知服务器协议升级
Upgrade: websocket #协议升级为websocket协议
这个就是Websocket的核心了,告诉Apache、Nginx等服务器:注意啦,发起的是Websocket协议,快点帮我找到对应的助理处理~不是HTTP。
Status Code:101 Switching Protocols  101 连接成功

 response Header:

Connection: upgrade #升级成功
Date: Thu, 12 Apr 2018 03:11:37 GMT
Sec-WebSocket-Accept: NbF/mYm1P/lNy0NsMWxYD1Wi1EE= #服务端处理之后的key
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Apache-Coyote/1.1
Upgrade: websocket

握手成功!

简单的代码示例:

jsp 客户端:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
	var webSocket = null;
	if (‘WebSocket‘ in window) {
		webSocket = new WebSocket("ws://localhost:8099/webSocketTest");
	} else {
		alert("浏览器不支持webSocket");
	}

	webSocket.onopen = function() {
		writeDiv("websocket连接ok");
	}

	webSocket.onmessage = function(event) {
		writeDiv("client 接受的消息是:" + event.data);
	}

	webSocket.onerror = function() {
		writeDiv("发生错误");
	}

	function sendMsg() {
		var val = document.getElementById("inputText").value;
		webSocket.send(" 客户端:" + val);
	}

	function closes() {
		webSocket.close();
	}

	webSocket.onclose = function() {
		webSocket.close();
		writeDiv("WebSocket連接關閉");
	}

	function writeDiv(innerHTML) {
		var html = document.getElementById(‘message‘).innerHTML;
		document.getElementById(‘message‘).innerHTML += innerHTML + ‘<br>‘;
	}
</script>
<body>

	<input type="text" id="inputText">
	<button id="but" onclick="sendMsg()">submit</button>
	<br>
	<button id="close" onclick="closes()">关闭webSocket连接</button>
	<br>
	<div id="message"></div>
</body>
</html>

服务端:

package com.tgb.SpringActivemq.controller;

import java.io.IOException;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.apache.log4j.Logger;

@ServerEndpoint("/webSocketTest")
public class webSocketController {

    private int count = 0;

    static  Set<Session> set = new HashSet<Session>();

    static final Logger logger = Logger.getLogger(webSocketController.class);

    private Session session;

    @OnOpen
    public void onOpen(Session sessio) {
        this.session = sessio;
        set.add(session);
        this.count++;
        logger.info("当前连接:" + this.count);
    }

    // 接受消息 处理
    @OnMessage
    public void onMessage(String message, Session ss) {
        logger.info("接受到的客户端消息是:" + message);
        Random r = new Random();
        int tet = r.nextInt(1000);
        try {
            ss.getBasicRemote().sendText("服务端发送的是:" + tet);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnError
    public void Onerror(Session s, Throwable th) {
        logger.info(th.getMessage());
    }

    @OnClose
    public void onClose(Session s) {
        try {
            s.close();
            set.remove(s);
            this.count--;
            logger.info("当前连接数:" + this.count);
            logger.info("CLOSE WEBSOCKET");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  

 

原文地址:https://www.cnblogs.com/msx-2018-begin/p/8806625.html

时间: 2024-11-09 00:39:51

webSocket的 原理 及 简单实现的相关文章

WebSocket的原理,以及和Http的关系

一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. Http协议本身只有1.0和1.1,也就是所谓的Keep-alive,把多个Http请求合并为一个. 二.WebSocket是什么样的协议,具体有什么优点. 首先,相对于Http这种非持久的协议来说,WebSocket是一种持久化的协议. 举例说明: (1)Http的生命周期通过Request来界

WebSocket的原理

前言:无聊逛知乎,就逛到H5的栏目去了,正好看到了关于Websocket的东西.个人是比较喜欢看这类风格的,转到博客分享,以便自己以后理解. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就

poj 2356 Find a multiple 鸽巢原理的简单应用

题目要求任选几个自然数,使得他们的和是n的倍数. 由鸽巢原理如果我们只选连续的数,一定能得到解. 首先预处理前缀和模n下的sum,如果发现sum[i]==sum[j] 那么(sum[j]-sum[i])%n一定为0,直接输出i+1~j就够了. 为什么一定会有解,因为sum从1~n有n个数,而模n下的数只有0~n-1,把n个数放入0~n-1个数里,怎么也会有重复,所以这种构造方法一定没问题. 其实可以O(n)实现,嫌麻烦,就二重循环无脑了. #include <iostream> #includ

搜索引擎原理之链接原理的简单分析

在google诞生以前,传统搜索引擎主要依靠页面内容中的关键词匹配搜索词进行排名.这种排名方式的短处现在看来显而易见,那就是很容易被刻意操纵.黑帽SEO在页面上推挤关键词,或加入与主题无关的热门关键词,都能提高排名,使搜索引擎排名结果质量大为下降.现在的搜索引擎都使用链接分析技术减少垃圾,提高用户体验.下面泡馆史明星就来简单的介绍链接在搜索引擎排名中的应用原理. 在排名中计入链接因素,不仅有助于减少垃圾,提高结果相关性,也使传统关键词匹配无法排名的文件能够被处理.比如图片.视频无法进行关键词匹配

编译原理(简单自动词法分析器LEX)

编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%BC%89.zip

HBase笔记:对HBase原理的简单理解

早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbase原理. 首先来点实在的东西,假如我们已经在服务器上部署好了Hbase应用,作为客户端或者说的具体点,本地开发环境如何编写程序和服务端的Hbase进行交互了? 下面我将展示这些,首先看工程的结构图,如下图所示: 接下来我们将hbase应用下lib文件夹里所有jar包都导入到工程lib目录下,还要把c

Windows-消息映射机制原理和简单的绘图技术

Windows-消息映射机制原理和简单的绘图技术 1.MFC消息映射机制 众所周知,Windows程序是基于消息编程的,但是在MFC中已经为我们封装好了这个框架的消息机制,我们需要了解它的实现原理,才能深入的学习和精通Visual C++. **(1).消息映射机制的原理: MFC消息映射机制的具体实现方法是,在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,即消息映射表.在消息映射表中,消息与对应的消息处理函数指针是成对出现的.某个类能处理的所有消息及其对应的消息处理函数的地址都

Lvs原理及简单实现

Lvs原理及简单实现 大纲: 一.集群概述 二.什么是Lvs?(what) 三.为什么要用Lvs?(why) 四.什么时候需要用Lvs?(when) 五.什么地方需要用Lvs?(where) 六.什么人来部署Lvs?(who) 七.Lvs支持的三种模式与十种算法(Scheduler) 八.如何部署Lvs之NAT模式?(How) 九.如何部署Lvs之DR模式? 一.集群简介: 计算机集群(Cluster)技术可以通过网络连接把一组互相独立工作的计算机高度紧密的连接起来,从而高效可靠的共同完成协同任

智能指针原理与简单实现(转)

以下实现没有考虑线程安全的问题. 智能指针:它的一种通用实现方法是采用引用计数的方法.智能指针将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1: 当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数: 对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数:这是因此左侧的指针指向了右侧指针所指向的对象,因此右指针所