一、http、socket、websocket介绍

1、HTTP(Hypertext Transfer Protocol):HTTP是一种应用层协议,用于在客户端和服务器之间传输超文本数据。它是基于请求-响应模型的,通过发送HTTP请求从服务器获取数据,并通过HTTP响应返回数据给客户端。HTTP是无状态的,每个请求和响应都是独立的,不保留状态信息。

2、Socket:Socket是一种底层的网络通信协议,用于实现进程间的通信。它提供了一种机制,使得应用程序能够通过网络进行数据传输。Socket通常用于实现客户端和服务器之间的双向通信,可以在两个终端之间建立持久连接,允许数据的双向流动。

3、WebSocket:WebSocket是一种基于TCP的全双工通信协议,它在HTTP基础上扩展而来。与HTTP不同,WebSocket允许服务器主动向客户端推送数据,而不需要客户端发起请求。WebSocket连接一旦建立,就可以保持长时间的双向通信,类似于Socket连接,但更加灵活和容易使用。

主要的区别:

  • HTTP是一种请求-响应协议,每个请求对应一个响应。而Socket和WebSocket是基于TCP的通信协议,支持全双工通信,允许实时的双向数据传输。

  • HTTP是无状态的协议,每个请求和响应都是独立的,不保留状态信息。而Socket和WebSocket可以保持连接状态,并允许在连接上持续传输数据。

  • HTTP通常用于客户端通过发送请求从服务器获取数据。Socket和WebSocket通常用于建立客户端和服务器之间的双向通信,支持实时的消息传递。

  • WebSocket是在HTTP协议基础上的扩展,使用了握手的方式建立连接,在连接建立后,双方可以随时互相发送消息。而HTTP和Socket需要在每次通信前先建立连接。

总结来说,HTTP适用于一次性请求和响应的场景,Socket适用于需要长时间、双向通信的场景,而WebSocket适用于实时通信、推送消息的场景。

二、工作流程

websocket的工作流程:

  1. 客户端通过向服务器发送 WebSocket 升级请求来启动连接,通常是通过 HTTP 连接。升级请求包含一个特殊的标头,表明客户端想要升级到 WebSocket 通信。
  2. 服务器响应升级请求,状态码为101,表示连接已成功升级为WebSocket通信。
  3. 从这一点开始,连接以全双工模式运行,这意味着客户端和服务器都可以随时向对方发送数据。WebSocket 协议提供了一种基于消息的通信模型,其中数据作为消息传输,而不是作为字节流传输。
  4. 消息使用紧凑的二进制格式传输,这比传统 HTTP 或 TCP 使用的基于文本的格式更有效。WebSocket 协议提供了一种机制,可以自动将大消息分成较小的数据包,并在另一端将数据包重新组合成原始消息。
  5. WebSocket 连接一直保持打开状态,直到客户端或服务器决定关闭它。关闭连接是一个简单的两步过程,包括发送关闭消息,然后等待另一端确认关闭消息。

    socket工作流程:
  6. 初始化:客户端和服务器应用程序各自创建一个套接字并将其绑定到特定的端口号。端口号用于标识网络上的应用程序。
  7. 连接建立:客户端通过向服务器的IP地址和端口号发送请求来建立与服务器的连接。服务器接受连接并为客户端创建一个新套接字。
  8. 数据交换:一旦建立连接,客户端和服务器就可以使用套接字相互交换数据。数据以数据包的形式发送,数据包是通过网络传输的小数据单元。
  9. 优雅关闭:当客户端和服务器完成交换数据时,它们通过向另一方发送消息以指示它们正在关闭连接来优雅地关闭连接。
  10. 终止:连接关闭后,客户端和服务器可以终止各自的套接字。

三、websocket代码实现

1、引入依赖

   <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、后端实现

2.1创建 WebSocketConfig 配置类,注入 websocket 服务

/**
* 开启WebSocket支持
**/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

2.2新建WebSocketServer服务端:WebSocket.java


/**
* @Description :
* @Date : 2023/7/17
* @Author :
*/
@ServerEndpoint(value = "/websocket/{userId}")
@Slf4j
@Component
@Data
public class WebSocket { /**
* concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
*/
private static ConcurrentHashMap<String, Session> webSocketSet = new ConcurrentHashMap<>(); //指定的sid,具有唯一性
private static String sid = ""; /**
* 连接建立成功调用的方法
*
* @param session 会话
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) throws Exception {
sid = userId;
webSocketSet.put(sid, session); //加入set中
log.info("【websocket消息】有新的连接,总数为:" + webSocketSet.size());
} /**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("参数信息:{}", message);
//群发消息
try {
log.info("【收到】,客户端{}的信息:{}", session, message);
} catch (Exception e) {
e.printStackTrace();
log.info("参数有误"); }
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
webSocketSet.remove(this);
if (session != null) {
try {
session.close();
log.info("【websocket消息】关闭了一个连接,总数为:" + webSocketSet.size());
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 发生错误时调用
*
* @param session 会话
* @param error 错误信息
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("连接异常!");
error.printStackTrace();
} /**
* 发送信息
*
* @param message 消息
*/
public void sendMessage(String message,String userId) throws IOException {
// 防止频繁断连问题引发的报错: The WebSocket session [3d] has been closed and no method (apart from close()) may be called on a closed session
Session session = webSocketSet.get(userId);
if (session.isOpen()) {
session.getBasicRemote().sendText(message);
}
} /**
* 自定义消息推送、可群发、单发
*
* @param message 消息
*/
public boolean sendAllInfo(String message, List<String> userIds) {
log.info("给用户" + userIds.toString() + "发送消息:" + message);
if (CollectionUtils.isEmpty(userIds)){return false;}
for (String userId:userIds){
try {
sendMessage(message,userId);
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
} }

注:@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。

onOpen 和 onClose 方法分别被@OnOpen和@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用的方法。

onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用的方法。

2.3 测试controller类

  @Resource
private WebSocket socketService;
@PostMapping("/test/socket")
public void testSocket(String msg){
try {
int i = 0;
while (true){
i++;
socketService.sendMessage("ces","1");
if (i == 100){
log.info("i到一百了");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

3、前端实现

<!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title></title>
</head> <body>
<button onclick="send()">发送消息</button>
</body> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
var websocket = null;
//判断浏览器是否支持websocket
if('WebSocket' in window) {
//实现化WebSocket对象
websocket = new WebSocket("ws://localhost:8088/websocket/1");
} else {
alert('该浏览器不支持websocket')
} //打开事件
websocket.onopen = function(event) {
console.log('建立连接');
}
//关闭事件
websocket.onclose = function(event) {
console.log("连接关闭");
}
//获得消息事件
websocket.onmessage = function(event) {
console.log("收到消息:" + event.data);
} //发生了错误事件
websocket.onerror = function(event) {
console.log("websocket 通信发生错误");
}
window.onbeforeunload = function(event) {
websocket.close();
} //发送消息
function send() { $.ajax({
type: "post",
url: "http://localhost:8088/test/socket",
data: {
msg: "23"
},
dataType: "json",
async: false,
success: function(data) {
console.log(data);
},
error: function(e) {
console.log(e);
}
});
}
</script> </html>

请求的时候出现跨域问题,解决,在后端加配置类


/**
* AJAX请求跨域
* @author Mr.W
* @time 2018-08-13
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer { @Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedHeaders(CorsConfiguration.ALL)
.allowedMethods(CorsConfiguration.ALL)
.allowCredentials(true)
.maxAge(3600);
}
}

http、socket以及websocket的区别(websocket使用举例)的更多相关文章

  1. python中socket、socketio、flask-socketio、WebSocket的区别与联系

    socket.socketio.flask-socketio.WebSocket的区别与联系 socket 是通信的基础,并不是一个协议,Socket是应用层与TCP/IP协议族通信的中间软件抽象层, ...

  2. 网络编程WebSocket 和socket、HTTP的区别和联系

    一.WebSocket 是什么? WebSocket是HTML5规范提出的一种协议:目前除了完犊子的IE浏览器,其他浏览器都基本支持.他是一种协议,万变不离其宗,也是基于TCP协议的:和HTTP协议是 ...

  3. 谈一谈Tomcat中webSocket,Jetty WebSocket 和Spring WebSocket以及github中Java-WebSocket.jar分别对Socket协议的角色定位以及效果的不同点;

    开局先上一张图:(http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html)   当前截图来自于apache的tomcat官网(问:为 ...

  4. HTTP 和 WebSocket的区别

    有关http和WebSocket 的区别网上有很多的质料. 个人在此仅仅是记录以下自己的学习心得,自己的理解. 1. http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要 ...

  5. 小白需要了解的Ajax和websocket的区别以及使用场景!

    在我们日常使用的互联网产品中,很多都是前后端数据的交互来完成的,说到数据交互就不得不提Ajax和websocket,它们可是数据交互的利器,那么它们分别是什么?websocket与Ajax轮询的区别又 ...

  6. WebSocket --为什么引入WebSocket协议

    Browser已经支持http协议,为什么还要开发一种新的WebSocket协议呢?我们知道http协议是一种单向的网络协议,在建立连接后,它只允许Browser/UA(UserAgent)向WebS ...

  7. websocket之一:websocket简介

    Websocket websocket为一次HTTP握手后,后续通讯为tcp协议的通讯方式. WebSocket 使用一种被称作“Upgrade handshake(升级握手)”的机制将标准的 HTT ...

  8. 一步一步学WebSocket (一) 初识WebSocket

    众所周知,Http协议是无状态的,并且是基于Request/Response的方式与服务器进行交互,也就是我们常说的单工模式.但是随着互联网的发展,浏览器与服务端进行双向通信需求的增加,长轮询向服务器 ...

  9. python全栈开发day115、116-websocket、websocket原理、websocket加解密、简单问答机器人实现

    1.websocket 1.websocket 与轮询 轮询: 不断向服务器发起询问,服务器还不断的回复 浪费带宽,浪费前后端资源 保证数据的实时性 长轮询: 1.客户端向服务器发起消息,服务端轮询, ...

  10. websocket之四:WebSocket 的鉴权授权方案

    引子 WebSocket 是个好东西,为我们提供了便捷且实时的通讯能力.然而,对于 WebSocket 客户端的鉴权,协议的 RFC 是这么说的: This protocol doesn’t pres ...

随机推荐

  1. 开源超全Lotus Domino Xpages 开发资料,Domino最新资料,lotus资料,xpages资料,Domino开源信息下载

    十年Domino资料,不断累积,精彩展示,从维护到开发,从CS到BS再变xpage,都是一步步过来,让Domino后台数据在在多个平台绽放 把这些开发技术文档分享出来,希望通过这个资料,为大家学习开发 ...

  2. Javaweb文件上传至服务器/从服务器下载

    Javaweb文件上传至服务器/从服务器下载 思路图 文件上传思路: 也可以直接看代码 判断是不是文件表单(判断form的enctype是不是="multipart/form-data&qu ...

  3. 数据库中的可视化和探索性:MongoDB的数据可视化和探索性工具

    目录 1. 引言 2. 技术原理及概念 2.1 基本概念解释 2.2 技术原理介绍 2.3 相关技术比较 3. 实现步骤与流程 3.1 准备工作:环境配置与依赖安装 3.2 核心模块实现 3.3 集成 ...

  4. 生成式预训练Transformer:探索其在自然语言处理领域的最新应用

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 4. 应用示例与代码实现讲解 生成式预训练Transformer:探索其在自然语言处理领域的最新应用 1. 引言 自然语言处理 (NLP) ...

  5. Linux系统运维之Zookeeper集群配置

    一.简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.ZooKeeper的目标就是封装好复杂易 ...

  6. SQL Sever 基础语法(增)

    SQL Sever  插入(Insert)基础语法详解 在SQL中,向表中插入数据是最基础的,任何对数据处理的基础就是数据库有数据,对于SQL而言,向表中插入数据有多种方法,本文列举3种: (一) 标 ...

  7. kubernetes(k8s):解决不在同一网段加入集群失败问题

    执行下面命令,将内外网进行映射. iptables -t nat -A OUTPUT -d 10.140.128.121 -j DNAT --to-destination 10.170.129.153 ...

  8. maven项目创建后添加resources等文件夹

    maven项目初始化只生成src/main/resources目录,但是这个不够用,我们得创建 src/main/java目录 src/test/java目录 src/test/resources目录 ...

  9. 【转载】Linux虚拟化KVM-Qemu分析(十)之virtio驱动

    原文信息 作者:LoyenWang 出处:https://www.cnblogs.com/LoyenWang/ 公众号:LoyenWang 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者 ...

  10. Mysql基础4-数据查询

    一.DQL介绍 DQL全称:Data Query Language(数据查询语言),用来查询数据库中表的记录. 关键字:select 二.DQL语法 select 字段列表 from 表名列表 whe ...