怎么设置网站字体,WordPress支持邮箱登录,wordpress 手机端模板,中国建设银行网站外汇WebSocket通信
WebSocket是一种基于TCP的网络通信协议#xff0c;提供了浏览器和服务器之间的全双工通信#xff08;full-duplex#xff09;能力。在WebSocket API中#xff0c;浏览器和服务器只需要完成一次握手#xff0c;两者之间就直接可以创建持久性的连接#xff…WebSocket通信
WebSocket是一种基于TCP的网络通信协议提供了浏览器和服务器之间的全双工通信full-duplex能力。在WebSocket API中浏览器和服务器只需要完成一次握手两者之间就直接可以创建持久性的连接并进行双向数据传输。这使得数据可以更快地从服务器传到浏览器而且减少了数据传输的数据量因为头信息比较小。在WebSocket API中服务器可以主动向客户端推送信息客户端也可以主动向服务器发送信息是真正的双向平等对话属于服务器推送技术的一种。HTTP协议和WebSocket协议的主要区别如下 连接方式HTTP协议是无短连接的。每次请求都需要建立新的连接请求结束后连接就断开。而WebSocket协议是长连接的客户端和服务器建立连接后直到其中一方主动断开连接才会断开。数据传输HTTP协议只能由客户端向服务器发起请求服务器返回响应数据。而WebSocket协议是全双工通信服务器和客户端都可以主动发送数据。性能开销由于HTTP协议每次请求都需要建立新的连接所以开销较大。而WebSocket协议建立连接后可以进行多次数据传输开销较小。数据格式HTTP协议传输的数据格式比较复杂包含了请求行、请求头、消息体等。而WebSocket协议传输的数据通过帧来传输数据格式比较简单。实时性HTTP协议的实时性不强需要客户端定时轮询服务器获取新的数据。而WebSocket协议可以实现服务器主动推送数据实时性较强。 WebSocket主要适用于以下几种场景 实时应用聊天应用、多人协作应用、在线游戏、实时购物等。实时数据推送股票、新闻、天气、设备状态等实时信息的推送。IOT物联网实时获取设备状态实时控制设备等。实时分析实时数据分析、实时监控系统等。
WebSocket入门案例 客户端 创建WebSocket对象在JavaScript中我们可以创建一个WebSocket对象指定要连接的服务器地址。 var ws new WebSocket(ws://localhost:8080/websocket);监听事件WebSocket对象提供了四个事件onopen、onmessage、onerror、onclose我们可以通过监听这些事件来处理WebSocket的各种情况。 ws.onopen function(event) {console.log(Connection open ...);
};ws.onmessage function(event) {console.log(Received Message: event.data);
};ws.onclose function(event) {console.log(Connection closed ...);
};ws.onerror function(event) {console.log(Error: event.data);
};发送数据WebSocket对象提供了一个send方法我们可以通过这个方法向服务器发送数据。 ws.send(Hello Server!);关闭连接当我们不再需要WebSocket连接时可以调用WebSocket对象的close方法来关闭连接。 ws.close();可以直接使用js写个小页面 !DOCTYPE HTML
html
headmeta charsetUTF-8titleWebSocket Demo/title
/head
bodyinput idtext typetext /button onclicksend()Send Message/buttonbutton onclickcloseWebSocket()Close/buttondiv idmessage/div
/body
script typetext/javascriptvar websocket null;var clientId Math.random().toString(36).substr(2);//判断当前浏览器是否支持WebSocketif(WebSocket in window){//连接WebSocket节点websocket new WebSocket(ws://localhost:8080/ws/clientId);}else{alert(Not support websocket)}//连接发生错误的回调方法websocket.onerror function(){setMessageInnerHTML(error);};//连接成功建立的回调方法websocket.onopen function(){setMessageInnerHTML(连接成功);}//接收到消息的回调方法websocket.onmessage function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose function(){setMessageInnerHTML(close);}//监听窗口关闭事件当窗口关闭时主动去关闭websocket连接防止连接还没断开就关闭窗口server端会抛异常。window.onbeforeunload function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById(message).innerHTML innerHTML br/;}//发送消息function send(){var message document.getElementById(text).value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();}
/script
/html 服务端 导入WebSocket的maven坐标 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId
/dependency导入WebSocket服务端组件WebSocketServer用于与客户端通信 package com.sky.websocket;import com.sky.handler.TurnoverReportVOEncoder;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;/*** WebSocket服务*/
Component
ServerEndpoint(value /ws/{sid},encoders {TurnoverReportVOEncoder.class}) // 为对象指定编码器目前是转成json发送给客户端
public class WebSocketServer {//存放会话对象private static MapString, Session sessionMap new HashMap();/*** 连接建立成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(sid) String sid) {System.out.println(客户端 sid 建立连接);sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** param message 客户端发送过来的消息*/OnMessagepublic void onMessage(String message, PathParam(sid) String sid) {System.out.println(收到来自客户端 sid 的信息: message);}/*** 连接关闭调用的方法** param sid*/OnClosepublic void onClose(PathParam(sid) String sid) {System.out.println(连接断开: sid);sessionMap.remove(sid);}/*** 群发** param message*/public void sendToAllClient(String message) {CollectionSession sessions sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}public void sendObjToAllClient(Object object) {CollectionSession sessions sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送对象--注意第4步骤需要为该对象指定一个编码器session.getBasicRemote().sendObject(object);} catch (Exception e) {e.printStackTrace();}}}} 导入配置类WebSocketConfiguration注册WebSocket的服务端组件ServerEndpointExporter package com.sky.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类用于注册WebSocket的Bean*/
Configuration
public class WebSocketConfiguration {Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}如果想向客户端推送封装好的对象在WebSocket中需要提供一个编码器来将这个对象转换为可以通过网络传输的格式通常是字符串或者二进制数据。 package com.sky.handler;import com.fasterxml.jackson.databind.ObjectMapper;
import com.sky.vo.TurnoverReportVO;import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;/*** projectName: sky-take-out* package: com.sky.handler* className: TurnoverReportVOEncoder* author: fangjiayueyuan* description: TODO* date: 2023/12/24 16:16* version: 1.0*/
public class TurnoverReportVOEncoder implements Encoder.TextTurnoverReportVO{private static ObjectMapper objectMapper new ObjectMapper();Overridepublic String encode(TurnoverReportVO turnoverReportVO) throws EncodeException {try {// 使用Jackson库将对象转换为JSON字符串return objectMapper.writeValueAsString(turnoverReportVO);} catch (Exception e) {throw new EncodeException(turnoverReportVO, 对象转换为JSON字符串时发生错误, e);}}Overridepublic void init(EndpointConfig endpointConfig) {// 这里可以进行编码器的初始化操作但在这个例子中我们不需要进行任何操作}Overridepublic void destroy() {// 这里可以进行编码器的清理操作但在这个例子中我们不需要进行任何操作}
} 导入定时任务类WebSocketTask定时向客户端推送数据 package com.sky.task;import com.sky.service.ReportService;
import com.sky.vo.TurnoverReportVO;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;Component
public class WebSocketTask {Autowiredprivate WebSocketServer webSocketServer;Autowiredprivate ReportService reportService;/*** 通过WebSocket每隔5秒向客户端发送消息*/Scheduled(cron 0/5 * * * * ?)public void sendMessageToClient() {webSocketServer.sendToAllClient(这是来自服务端的消息 DateTimeFormatter.ofPattern(HH:mm:ss).format(LocalDateTime.now()));}/*** 通过WebSocket每隔5秒向客户端发送消息*/Scheduled(cron 0/5 * * * * ?)public void sendObjMessageToClient() {TurnoverReportVO turnoverStatistics reportService.getTurnoverStatistics(LocalDate.parse(2023-01-01), LocalDate.now());webSocketServer.sendToAllClient(传个对象过去);webSocketServer.sendObjToAllClient(turnoverStatistics);}
}
RPC通信
**RPCRemote Procedure Call**是一种通信协议它允许运行在一台计算机上的程序调用另一台计算机上的程序中的函数或方法就像调用本地函数一样无需程序员显式处理底层的网络细节。
RPC的主要特征包括 透明性对于调用者来说远程过程调用和本地过程调用是透明的调用者无需关心过程调用的是本地过程还是远程过程。 语言无关性RPC通常支持多种编程语言只要两个通信的程序遵循同一RPC协议它们就可以进行通信无论它们是用什么编程语言编写的。 同步性RPC通常是同步的也就是说当一个RPC调用发出后调用者会停止执行直到得到结果。然而也有一些RPC系统支持异步调用。
为什么使用RPC 简化分布式系统的开发RPC隐藏了底层的网络通信和数据传输的复杂性使得开发分布式应用更加简单。 提高代码的可重用性通过RPC可以将一些通用的功能实现为服务然后在多个应用中重用这些服务。 提高系统的可扩展性通过RPC可以将一个大的系统分解为多个可以独立开发和部署的小的服务。
RPC的替代方案
RESTful APIRESTful API是一种基于HTTP协议的通信方式它使用HTTP的方法如GET、POST、PUT、DELETE等来操作资源。RESTful API比RPC更简单更易于使用但它不如RPC灵活因为它只能使用HTTP协议而RPC可以使用任何传输协议。消息队列消息队列是一种异步的通信方式它允许程序通过发送和接收消息来进行通信。消息队列可以解耦发送者和接收者使得它们可以独立地扩展和失败。然而消息队列的使用比RPC更复杂因为它需要处理消息的发送、接收、存储和确认。
RPC入门案例
以Thrift为例 定义数据类型和服务接口使用Thrift的IDL接口定义语言定义数据类型和服务接口然后通过Thrift的编译器生成对应语言的代码。 namespace java com.sankuai.mdp.thriftstruct User{1:i32 id2:string name3:i32 age0
}service UserService{User getById(1:i32 id)bool isExist(1:string name)
}通过Thrift编译器生成Java代码会生成两个对象User、UserService thrift --gen java HelloWorld.thrift服务端代码实现UserService.Iface接口启动服务端. package com.sankuai.mdp.thriftserversnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.User;
import com.sankuai.mdp.thriftapisnapshot.entity.UserService;
import org.apache.thrift.TException;/*** projectName: thrift-api-snapshot* package: com.sankuai.mdp.thriftserversnapshot.service.impl* className: UserServiceImpl* author: fangjiayueyuan* description: TODO* date: 2023/12/17 21:33* version: 1.0*/
public class UserServiceImpl implements UserService.Iface{Overridepublic User getById(int id) throws TException {System.out.println(-----调用getById-----);User user new User();user.setId(id);user.setName(dog);user.setAge(18);return user;}Overridepublic boolean isExist(String name) throws TException {return false;}
} package com.sankuai.mdp.thriftserversnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.UserService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;/*** projectName: thrift-api-snapshot* package: com.sankuai.mdp.thriftserversnapshot.service.impl* className: SimpleService* author: fangjiayueyuan* description: TODO* date: 2023/12/17 21:59* version: 1.0*/
public class SimpleService {public static void main(String[] args) {try{TServerTransport serverTransport new TServerSocket(9090);UserService.Processor processor new UserService.Processor(new UserServiceImpl());TBinaryProtocol.Factory protocolFactory new TBinaryProtocol.Factory();TSimpleServer.Args targs new TSimpleServer.Args(serverTransport);targs.processor(processor);targs.protocolFactory(protocolFactory);TServer server new TSimpleServer(targs);server.serve();} catch (TTransportException e) {throw new RuntimeException(e);}}
}客户端代码调用服务端的方法就像调用本地方法一样 package com.sankuai.mdp.thriftclientsnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.User;
import com.sankuai.mdp.thriftapisnapshot.entity.UserService;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;/*** projectName: thrift-api-snapshot* package: com.sankuai.mdp.thriftclientsnapshot.service.impl* className: SimpleClient* author: fangjiayueyuan* description: TODO* date: 2023/12/17 21:58* version: 1.0*/
public class SimpleClient {public static void main(String[] args) {TTransport transport null;try {transport new TSocket(localhost, 9090);TBinaryProtocol protocol new TBinaryProtocol(transport);UserService.Client client new UserService.Client(protocol);transport.open();User result client.getById(1);System.out.println(Result: result);} catch (TTransportException e) {e.printStackTrace();} catch (TException e) {throw new RuntimeException(e);} finally {if (transport ! null) {transport.close();}}}
} 先后启动运行服务端SimpleService.java、客户端代码SimpleClient.java Git