一、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. RESTful API 简介

    RESTful API 简介 想必使用过 PHP.JSP 这一类服务器动态页面技术的程序员应该都还记得,在使用这种传统的动态页面架构构建应用程序的时候,用于描述用户界面的 HTML 页面通常都是在服务 ...

  2. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-2-playwright的API及其他知识

    1.简介 上一篇宏哥已经将Python+Playwright的环境搭建好了,而且也简单的演示了一下三款浏览器的启动和关闭,是不是很简单啊.今天主要是把一篇的中的代码进行一次详细的注释,然后说一下pla ...

  3. 在 Linux 上给用户赋予指定目录的读写权限

    在 Linux 上指定目录的读写权限赋予用户,有两种方法可以实现这个目标:第一种是使用 ACL (访问控制列表),第二种是创建用户组来管理文件权限,下面会一一介绍.为了完成这个教程,我们将使用以下设置 ...

  4. ics-05

    挺有意思的一题 攻防世界->web->ics-05 打开题目链接,就是一个很正常的管理系统,只有左侧的可以点着玩 并且点到**设备维护中心时,页面变为index.php 查看响应 发现云平 ...

  5. 如何在2023年开启React项目

    在这里,我想给你一个新的React项目入门的简要概述.我想反思一下优点和缺点,反思一下作为一个开发者所需要的技术水平,反思一下作为一个React开发者,每个启动项目都能为你提供哪些功能.最后,你将了解 ...

  6. 你是怎么学习 Java 技术的?

    一.Java 语言 Java 语言不只是一门语言. Java 学习不是一蹴而就就可以达成的,它是一个循序渐进,由浅入深,由表及里的过程.尤其需要注意的是不能有浅尝辄耻,不求甚解的态度.每个地方只抓一点 ...

  7. unity添加Mysql的dll以及发布的问题

    最近在做一个unity项目中,要读取数据库,还是MySql的数据库.遇到了很多问题,写出来供大家参考一下. 关于unity引用第三方的Mysql.data.dll的问题: 这个地方有一个难点,正常的C ...

  8. .NET指定图片地址下载并转换Base64字符串

    需求描述 需要调用第三方图片上传接口上传图片,对方图片格式只能接收Base64字符串.所以我们需要将系统服务器的图片通过Url下载下来,然后转换成Base64字符串.接下来我们将使用HttpClien ...

  9. 使用 ProcessBuilder API 优化你的流程

    ProcessBuilder 介绍 Java 的 Process API 为开发者提供了执行操作系统命令的强大功能,但是某些 API 方法可能让你有些疑惑,没关系,这篇文章将详细介绍如何使用 Proc ...

  10. javaSE 温故而知新

    重温 javaSE 前言:有地基才能有高楼大厦 目录 重温 javaSE 认识java Java基础 1.数据类型 1.1 基本数据类型: 1.2 引用数据类型 1.3 基本数据类型的包装类 1.4 ...