文章目录
- WebSocket是什么
- WebSocket通信原理和机制
- WebSocket协议是什么
- WebSocket协议和Http协议有什么区别
- WebSocket常用在那些场景
- Springboot集成WebSocket
- pom依赖
- java相关代码
- config
- component
- html代码
- 页面访问效果
WebSocket是什么
🍊WebSocket是一种网络通信协议,它提供了在单个TCP连接上进行全双工通信的能力。这意味着在一个连接上,服务器和客户端都可以同时发送和接收数据。
🍊WebSocket与HTTP协议不同,它使用了独立的端口,并且在建立连接后,不需要在每次数据传输时重新建立连接。这使得它特别适合于实时应用程序,例如聊天,在线游戏和股票交易等,这些应用程序需要高速,双向的数据传输。
🍊WebSocket协议是HTML5标准的一部分,因此它可以在现代浏览器中使用。WebSocket API可以在JavaScript中使用,这样就可以在网页上直接使用WebSocket进行通信。
🍊WebSocket使用了一种称为握手的连接建立机制,服务器和客户端在建立连接之前需要进行握手。握手是通过HTTP协议完成的,但是一旦建立连接后,数据传输将使用WebSocket协议。
WebSocket通信原理和机制
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它使得客户端和服务器之间能够进行双向通信而不必进行多次HTTP请求和响应。
WebSocket通信的流程如下:
- 客户端发送一个HTTP请求,请求的目的是为了要建立一个WebSocket连接。
- 服务器收到请求后,给出一个HTTP响应,并升级连接到WebSocket协议。
- 客户端和服务器之间建立一个WebSocket连接。
- 客户端和服务器之间可以进行双向通信,发送文本和二进制数据。
- 当客户端或服务器关闭连接时,WebSocket连接也会关闭。
与 HTTP 通信不同的是,WebSocket 通信是基于TCP的,所以它是一个持久连接。它允许服务器主动发送信息给客户端,而不是等待客户端的请求。这使得 WebSocket 通信成为了实现实时应用的理想选择。
如下图所示,发起一个websocket链接之后,请求和响应的参数里会有一些websocket相关的参数,该报文中有一个upgrade首部,它的作用是告诉服务端需要将通信协议切换到websocket
WebSocket协议是什么
🍊WebSocket协议是一种网络协议,它定义了浏览器和服务器之间的通信协议。WebSocket协议实现了客户端和服务器之间的双向通信,而不是传统的单向通信。
🍊WebSocket协议是基于TCP协议的,并且在建立连接时使用了HTTP协议。在建立连接时,客户端发送一个HTTP请求到服务器,请求升级连接到WebSocket协议。服务器收到请求后,给出一个HTTP响应,并升级连接到WebSocket协议。之后客户端和服务器就可以通过WebSocket协议进行双向通信了。
🍊WebSocket协议是一种全双工协议,它允许服务器主动发送信息给客户端,而不是等待客户端的请求。这使得WebSocket协议成为了实现实时应用的理想选择。
🍊WebSocket协议是IETF(Internet Engineering Task Force)标准化组织于2011年发布的一种新的协议,并且在2013年正式成为因特网标准。
WebSocket协议和Http协议有什么区别
WebSocket协议和HTTP协议有以下几点区别:
- 通信方式不同: HTTP协议是一种请求-响应协议,客户端发送请求给服务器,服务器返回响应。而WebSocket协议是一种全双工协议,客户端和服务器都可以主动发送消息。
- 链接状态不同: HTTP协议是无状态的,每次请求都是独立的。而WebSocket协议是有状态的,建立了连接之后,客户端和服务器之间可以维持长连接。
- 数据传输不同: HTTP协议是基于文本的,而WebSocket协议是基于二进制的。
- 延迟不同: HTTP协议每次请求都需要建立连接,等待响应,传输数据,释放连接,这整个过程都需要一些时间。而WebSocket协议只需要建立一次连接,之后就可以高效地进行数据传输,所以延迟更小。
WebSocket常用在那些场景
常见的应用场景如下:
- 在线聊天:实现实时的文本聊天功能。
- 直播和视频会议:实现实时的音频和视频传输。
- 游戏:实现实时的游戏状态同步和控制。
- 实时监控和控制:实现实时的硬件监控和控制。
- 数据可视化:实现实时的数据可视化和分析。
- 在线协作:实现实时的文档协作和编辑。
- 智能家居:实现实时的智能家居控制。
- 推送消息:实现实时的推送消息功能
这些场景中,WebSocket的实时通信特性使得WebSocket成为了一种理想的选择。
Springboot集成WebSocket
🍊使用springboot+WebSocket+JavaScript实现一个简单的示例
pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
<java.encoding>UTF-8</java.encoding>
<slf4j.version>1.7.30</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot集成websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- 引入日志管理相关依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.14.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<target>${java.version}</target>
<source>${java.version}</source>
<encoding>${java.encoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<arguments>-Prelease</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
java相关代码
config
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
* @author
* @date 2023年01月29日 14:07
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private WebSocketHandler webSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/websocket").setAllowedOrigins("*");
}
}
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author
* 解决跨域问题
* @date 2023年01月29日 14:46
*/
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, X-Requested-With");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
component
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author
* @date 2023年01月29日 14:08
*/
@Component
public class WebSocketHandler extends TextWebSocketHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
private static final List<WebSocketSession> sessions = new ArrayList<>();
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
LOGGER.info("Received message: {}", message.getPayload());
for (WebSocketSession webSocketSession : sessions) {
try {
webSocketSession.sendMessage(message);
} catch (IOException e) {
LOGGER.error("Error: {}", e.getMessage());
}
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.add(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
sessions.remove(session);
}
}
html代码
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Example</title>
</head>
<body>
<input type="text" id="messageInput">
<button onclick="sendMessage()">Send</button>
<script>
var socket = new WebSocket("ws://localhost:8080/websocket");
socket.onopen = function(event) {
console.log("WebSocket is open now.");
};
socket.onmessage = function(event) {
var message = event.data;
console.log("Received message: " + message);
};
socket.onclose = function(event) {
console.log("WebSocket is closed now.");
};
function sendMessage() {
var message = document.getElementById("messageInput").value;
socket.send(message);
}
</script>
</body>
</html>
页面访问效果
访问页面时开启websocket连接,输入文字时能接收到对应的反馈信息
客户端发送和接收到的信息