单工指的是信息是单通道单向的,信息只能从A传达到B,但是不能由B传达到A。比如广播站和收音机,收音机只能单方面接受广播站的信息。
半双工则是单通道双向的,信息可以从A到B,也可以由B到A,但是这个过程不能同时进行。比如说对讲机,A摁下按钮说话的时候B只能听着,只有A发言结束,松开按钮之后,B才能说话。
全双工是双向双通道的,信息可以从A到B,也可以由B到A。这个过程可以同时进行,就像打电话。A说话的同时B也可以说话
简单来说,请求响应模式就是客户端向服务器发送一个请求,服务器处理请求然后返回一个响应。比如说我现在点了一个叉号。发送了点叉号的请求,然后服务器会处理这个请求,解析它的头部,验证之类的,然后响应——关掉页面。
在这个过程中,连接在发送请求时建立,在响应之后立刻关闭。这样的话如果发送多个请求的话,就会有延迟。因为每次都需要建立一个新的连接。
而持久连接的含义就是直接创建一个通道,就不需要重复创建连接的过程了,可以大大的减少延迟。不过这里说的持久连接本质上还是基于请求-响应的通信基础仍是单向的。
WebSocket则引入了一种全新的通信机制,它允许在一个持久的双向连接上进行实时的双向数据传输,避免了传统请求-响应模式的一些限制,特别适用于需要实时更新和双向通信的应用场景。
TCP(Transmissions Control Protocol)(传输控制协议)
TCP是一种面向连接的、可靠的传输层协议。它负责在两台计算机之间建立可靠的通信连接,确保数据的可靠传输。TCP提供了一种流控制机制,能够确保数据按照顺序、可靠地传送。它是 OSI 模型中的传输层协议,用于在网络上可靠地传输数据。TCP协议的工作方式是通过建立连接、数据传输、连接释放等步骤来实现可靠的数据传输。
HTTP(Hypertext Transfer Protocol)超文本传输协议
HTTP是一种应用层协议,用于在Web上传输超文本(Hypertext)。HTTP是一个无状态的协议,每个请求和响应之间都是相互独立的,服务器不会在两个请求之间保留任何状态信息。它基于客户端-服务器模型,其中客户端通过发送HTTP请求与服务器进行通信,而服务器则通过发送HTTP响应进行响应。
HTTP常用于Web浏览器和Web服务器之间的通信,用于获取和传输Web页面、图像、样式表、脚本等资源。HTTP协议基于TCP协议,通常使用TCP的80端口。虽然HTTP是一个简单而灵活的协议,但它是无连接的,每次请求都需要建立一个新的连接,这可能导致一些性能上的开销。
简单来说HTTP是TCP的一种特殊情况。HTTP是基于TCP的。类似于TCP是铁,而HTTP是铁锭
TCP/IP(Transmission Control Protocol/Internet Protocol)是一组用于在网络上进行通信的协议集合,它是互联网的基础协议。TCP/IP协议族由两个主要协议层组成:传输层的TCP(Transmission Control Protocol)和网络层的IP(Internet Protocol)。
TCP(Transmission Control Protocol):
TCP是一种面向连接、可靠的传输层协议。它负责在两台计算机之间建立可靠的通信连接,确保数据的可靠传输。TCP提供了流控制、拥塞控制等机制,确保数据按照顺序、完整地传递。它是可靠的、面向连接的协议,适用于需要可靠数据传输的应用场景。
IP是一种网络层协议,负责在网络上进行数据包的路由和寻址。它定义了数据包的格式,包括源地址和目标地址等信息。IP协议是无连接的,它主要关注的是如何在网络中正确地将数据包从源传输到目的地。
TCP/IP协议族还包括其他一些协议,如UDP(User Datagram Protocol)、ICMP(Internet Control Message Protocol)等,这些协议共同构成了互联网通信的基础。
TCP/IP协议族是互联网的基础协议,它使得不同类型的计算机和网络设备能够在互联网上进行通信。在互联网中,数据被分割成小的数据包,通过TCP协议传输,而这些数据包则通过IP协议进行路由,从源到目的地。
TCP(Transmission Control Protocol):
用于在网络上建立可靠的、面向连接的通信。TCP确保数据的有序、可靠传输,提供流控制和拥塞控制机制。
用于在网络上进行数据包的路由和寻址。IP定义了数据包的格式,包括源地址和目标地址等信息。IPv4和IPv6是两个主要版本。
与TCP类似,是一种传输层协议,但是它是无连接的,不保证数据的可靠性。UDP适用于一些对实时性要求较高,可以容忍少量数据丢失的应用场景。
ICMP(Internet Control Message Protocol):
主要用于在IP网络上发送错误消息和操作信息,通常由网络设备(如路由器)用于通知网络中的错误情况。
HTTP(Hypertext Transfer Protocol):
用于在Web上进行超文本传输的应用层协议。HTTP定义了客户端和服务器之间的通信规则,通常使用TCP作为传输层协议。
HTTPS(Hypertext Transfer Protocol Secure):
基于HTTP的安全版本,使用SSL/TLS协议进行加密通信,以提高数据传输的安全性。
用于在网络上进行文件传输的应用层协议。FTP定义了文件传输的规范,包括文件上传、下载等操作。
SMTP(Simple Mail Transfer Protocol):
用于在网络上传输电子邮件的协议。SMTP定义了邮件的传输规则,确保电子邮件从发件人传输到收件人。
这些协议共同构成了TCP/IP协议族,为互联网上的通信提供了基础。它们规定了数据在网络中的传输方式、格式和处理规则,使得不同设备和系统能够在互联网上进行有效的通信。
假设你需要和商场里的某个店铺进行详细的交流,你会选择打电话。电话服务提供了一种可靠、有序的通信方式,就像TCP确保了网络上的可靠通信一样。
商场里每个店铺都有自己的位置,你需要知道每个店铺的地址才能找到它。IP协议就像商场的地址系统,确保数据包从发送方到目的地的正确路由。
如果你只是想简单地告诉某个朋友你在商场的哪个区域,你可能选择发个传呼。传呼服务是一种无连接的通信方式,就像UDP协议,适用于一些快速、不那么关注可靠性的通信。
当你在商场里购物时,你可能会使用订单形式来选购商品。HTTP就像一种规定了如何提交和获取信息的协议,用于在Web上进行超文本传输。
如果你购物后需要将大量商品送到家,你可能会选择快递服务。FTP协议就像一种文件传输服务,用于在网络上进行文件的上传和下载。
如果你需要向商场里的某个店铺寄送一封信,SMTP就像一种电子邮件的邮寄服务,确保你的信件能够正确发送到目的地。
6.HTTP是基于TCP的,那么全双工通信也是基于TCP的,它和HTTP是类似的吗,同理,WebSocket呢
全双工通信和HTTP的关系是可以通过比喻理解的。HTTP是一种协议,就像我们在之前的类比中提到的电话服务一样。在电话服务中,有单工通信(你说完对方才能说)和全双工通信(你和对方可以同时说话)两种情况。
HTTP最初是设计为单向的请求-响应模型,类似于你打电话给商店询问信息,商店回答你的问题。这是一种单向通信的模式,即客户端发送请求,服务器回复响应。
然而,全双工通信更像是一种对话,就像你和朋友之间的电话对话一样,你们可以同时说话。在网络中,WebSocket就提供了这样的全双工通信机制。WebSocket协议允许在同一个TCP连接上进行实时的双向数据传输,而不是像HTTP那样需要为每个请求-响应建立新的连接。
虽然HTTP可以通过长连接和持久连接的方式实现一些类似实时性的效果,但WebSocket更专注于实现全双工通信,适用于需要频繁更新和实时性较高的应用场景,比如在线聊天、实时数据推送等。所以,全双工通信和HTTP在通信模型上有区别,而WebSocket作为协议更适合实现全双工通信。
简单来说:全双工,半双工,单工本质上指的是通讯方式,是抽象概念。而HTTP,TCP都是具体概念。因为HTTP是请求响应模式,所以它是单工的。但是TCP有很多种方式,所以TCP既有可能是单工也有可能是双工,需要根据具体情况来看。
而webSocket是虽然也基于TCP的协议,但它提供了全双工通信的能力。WebSocket允许在同一个TCP连接上进行双向实时数据传输,适用于需要实时性、频繁更新的应用场景。在使用TCP时,通信方式(全双工、半双工)实际上取决于应用程序如何使用这个通道。TCP本身是全双工的,但应用程序可以选择使用它来实现单向通信,也可以使用它来实现双向通信。WebSocket是一种在TCP基础上实现全双工通信的协议,更适合需要实时性的应用。
被@serverEndpoint注解标注的类被称为webSocket的服务器端点类。每一个WebSocketController(被标注的类)的实例,都是一个与客户端相连的通道。并处理相关的事件(一般是三类,打开,关闭和接受消息,即被注解标注的三个方法)
@serverEndpoint后面的URL就是连接这个webSocket的URL,通过这个URL(其实是起到一个标识的作用),客户端可以与服务器相连(且是持久相连的全双工通信通道)。
原理是,用户通过这个URL,找到这个webSocketController类,然后实例化生成通道。如果现在有两个@ServerEndpoint标注的类,一个叫test1,一个叫test2。一个路径是test/1.一个路径是test/2。那么到时候前端的连接写的是哪个,就创建哪个类的实例(因为两个类中的方法不同,处理的问题自然也不相同)
@ServerEndpoint注解的类是WebSocket通信的入口点,负责处理与客户端建立的连接,并定义了在不同事件发生时的行为。每个连接都会有一个对应的实例,允许我们以面向对象的方式管理和处理WebSocket通信。
也就是说,带着@ServerEndpoint的类就是端点类。初始化一个带着@ServerEndpoint的类实例,就是创建了一个具体的端点。这个端点的作用是和客户端创建连接通道
@ServerEndpoint后面的路径这就好比是电信的热线,10010。如果有另一个类可能就是10086,就是中国移动了。这个10010就是上面所说的那个URL,每个打过来的用户就是一个客户端(客户),连接的方式是全双工,客服可以说话,用户也可以说话。每一个具体的客服人员,就是一个端点的实例。
2.后台并没有实例化这个端点类的代码,它是何时进行实例化的呢?
WebSocket端点类的实例化是由WebSocket容器自动管理的,而不是在应用代码中手动实例化。当客户端请求建立WebSocket连接时,WebSocket容器会负责实例化相应的@ServerEndpoint注解的类。
WebSocket容器在运行时负责管理WebSocket端点的生命周期。基本流程如下:
当有客户端请求建立WebSocket连接时,客户端会发送一个WebSocket握手请求。
WebSocket容器(例如,Java中的Java API for WebSocket或其他实现)会拦截这个握手请求,并根据请求中的路径信息以及@ServerEndpoint注解的配置,决定将请求分派给哪个具体的端点类。
一旦确定了将请求分派给哪个端点类,WebSocket容器会负责实例化这个类的一个新实例。这个实例将负责处理与特定连接相关的事件。
实例化后,端点类的生命周期开始,会触发@OnOpen注解的方法,执行一些初始化操作。
在连接建立后,端点类会处理接收到的消息和其他事件,例如@OnMessage注解的方法用于处理接收到的消息。
当客户端关闭连接或其他原因导致连接断开时,容器会触发@OnClose注解的方法,允许端点类执行清理工作。
注意这里提到了webSocket的生命周期,因为它被@ServerEndpoint标注了,所以它被webSocket容器管理生命周期。就和之前的@compoent注解标注的类会被Springboot的容器管理一样。因此
会要求发布的时候注销掉。因为如果@Component注解其效果的话,它的生命周期就会被Spring容器接管。那么它被连接时的初始化以及自动运行的三个被注解标注的方法就都不能使用了
但是,如果写了webSocket配置类,并且用@bean注册了ServerEndpointExporter的话,就可以这样写了
注意前端只需要连接这个webSocket就可以实例化一个webSocket对象,或者说只有前端连接这个webSocket的时候才会创建一个webSocket对象。这个对象就只负责这个客户端的相关操作,这个客户端也只由这个对象负责通讯。
const socket = new WebSocket("ws://localhost:8087/eco/websocket/9e0fa13aa279483dbb0c45c3c0d76969");
WebSocket对象,通过指定的WebSocket URL建立连接。一旦连接建立,
WebSocket对象就可以通过其相关的事件处理函数来处理不同的事件。例如,你可以添加一个回调函数来处理连接建立时的事件:
前端后续代码中的socket就是这时候创建出来的WebSocket对象。(而event则是事件对象包含有关 WebSocket 事件的信息,如后续的onopen时间等等)
所以连接开始后不仅是后端会创造一个对象,前端其实也会创建一个对象(这两个对象就像两个端点连起来整个通讯过程,它们在整个通讯过程中都是一一对应的)
在前端,通过new WebSocket(url)创建了一个WebSocket对象。这个对象表示前端与服务器之间的连接通道。
当前端发起WebSocket连接请求时,后端WebSocket容器负责实例化相应的@ServerEndpoint注解的类,即WebSocket端点类。每个实例代表一个与客户端建立的连接。
在连接建立期间,前端的WebSocket对象与后端的WebSocket端点实例是一一对应的。前端对象与后端实例之间建立了一个双向通信的通道,可以通过这个通道进行实时的双向数据传输。
在前端,通过WebSocket对象的事件处理函数(例如onopen、onmessage、onclose)处理与连接相关的事件。在后端,通过@OnOpen、@OnMessage、@OnClose等注解的方法处理相应的事件。
当前端或后端其中一方关闭了WebSocket连接,通道的对应关系就会结束。这时前端的WebSocket对象会触发onclose事件,后端的@OnClose注解方法也会被调用,表示连接已关闭。
const socket = new WebSocket("ws://localhost:8087/eco/websocket/test/'9e0fa13aa279483dbb0c45c3c0d76969'");
socket.onopen = function(event) {
console.log("WebSocket connection opened");
socket.send("Hello, server!");
socket.onmessage = function(event) {
console.log("Received message: " + event.data);
socket.onclose = function(event) {
console.log("WebSocket connection closed");
注意,这里的后面三个方法都是回调方法(因为Java没有类似的回调写法,所以这里先不科普了,后面可能会开专题)
既然前端是回调方法,那么自然是先有后端进行方法,然后前端再进行回调。
const socket = new WebSocket("ws://localhost:8087/eco/websocket/test/'9e0fa13aa279483dbb0c45c3c0d76969'");
此时连接一旦建立,就会立刻实例化一个后端的webSocket对象出来
之后,webSocket容器开始控制这个对象的生命周期,运行第一个函数onOpen。
session.getBasicRemote().sendText
当前端接收到消息之后,就会调用另一个onmessage方法。
同理,当前端想发信息的时候使用的方法是socket.send。这时候后端也会调用对应的onMessage方法来处理。
如果过程中出错,后端会调用OnError方法,如果要关闭的话也会调用OnClose方法(这个和析构函数的原理差不多,两个方法都是再发生事件时需要做的额外处理,而不是事件本身。webSocket实例
的关闭由webSocket容器来决定,OnClose只是执行结束前需要做的业务罢了)
然后当这里的onclose运行之后,前端的onclose方法也会运行。再然后就是容器控制通道关闭了
这里是GTP补充说明(上面说的已经比较清楚了,这里更加官方一点)
在前端创建 const socket = new WebSocket("ws://localhost:8087/eco/websocket/test/'9e0fa13aa279483dbb0c45c3c0d76969'"); 这一行代码时,实际上是在尝试建立 WebSocket 连接,并创建了一个 WebSocket 对象(socket)。
后端的 WebSocket 对象的实例化是由 WebSocket 容器负责的,不需要你在代码中显式实例化。当前端的 WebSocket 连接建立后,WebSocket 容器会自动创建一个与该连接关联的后端 WebSocket 对象,然后执行 @OnOpen 注解的方法。
在 @OnOpen 注解的方法中,通常用于进行与连接相关的初始化操作,例如向客户端发送初始信息,处理连接参数等。
当前端建立连接后,通过设置 socket.onopen、socket.onmessage、socket.onclose 等回调函数,来处理相应的 WebSocket 事件。
在后端,使用 session.getBasicRemote().sendText() 方法可以向前端发送消息。这通常在后端需要主动向前端推送信息时使用,例如进度更新、通知等。
在前端,通过 socket.send() 方法可以向后端发送消息。后端需要使用 @OnMessage 注解的方法来处理接收到的消息。
异常(@OnError)和关闭(@OnClose)处理方法提供了在连接发生异常或关闭时执行额外逻辑的机会。这在释放资源、清理状态等方面很有用。
在后端的 @OnClose 方法中删除对应的 PID 是为了在通道关闭时清理相关资源,确保后续使用不会受到影响。
注意,@Message的参数是有要求的,它只能有一个非session的参数,一般是String。这个String就是前端send的消息
在Java中,使用 @OnMessage 注解时,方法的参数是有一定规范的。通常情况下,@OnMessage 注解的方法只能包含一个 String 或 ByteBuffer 类型的参数,表示接收到的消息内容。这是因为WebSocket的核心规范定义了这样的规则。
如果你希望接收多个参数,可以考虑将这些参数拼装成一个字符串,然后在方法内部进行解析。例如:
public void onMessage(Session session, String combinedMessage) throws IOException {
// 解析 combinedMessage,获取多个参数的值
String[] messages = combinedMessage.split(",");
String message1 = messages[0];
String message2 = messages[1];
而对于@onOpen而言,一般只允许有一个参数session。但是可以通过路径传值
public void onOpen(Session session, @PathParam("pid") String pid,String text,String text1) throws IOException
那么后面两个参数永远都会是空参数(因为@OnOpen是由容器开启的,自然不会传递任何其他的参数,pid是路径参数,所以可以拿到)
而且前端只要socket.send了,就会触发onMessage的方法
public class WebSocketConfig {
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
主要作用就是注册了一个ServerEndpointExporter(关于如何注册的,容器那一篇再进行具体的解释)
重要的是ServerEndpointExporter。这是 Spring Boot 对 WebSocket 的支持类之一。它会扫描并注册使用
@ServerEndpoint 注解的 WebSocket 端点,使它们成为 Spring 管理的 Bean。这样,WebSocket 就能够在 Spring Boot 中正常工作。然后之前说到的,@component可能会发生冲突(我之前理解有误)。但是
为了使被 @ServerEndpoint 标注的类同时具备 WebSocket 容器和 Spring 容器的特性,通常需要两个步骤:
@ServerEndpoint 标注的类上添加 @Component 或其他 Spring 容器相关的注解,使其成为 Spring Bean。这样,该类就能够被 Spring 容器管理,并享受到 Spring 提供的依赖注入、事务管理等功能。
ServerEndpointExporter,以便激活 WebSocket 功能,并将 @ServerEndpoint 标注的类纳入 WebSocket 容器的管理。这通常是通过 @Bean 方法返回 ServerEndpointExporter 来实现的。
如果写了配置类之后,再在websocket端点类上面加上@Component。就可以同时具备 WebSocket 容器和 Spring 容器的特性
标签:协议,HTTP,WebSocket,前端,TCP,相关,websocket,连接 From: https://www.cnblogs.com/052160fh/p/18084389