长轮询之websocket

官方文档

背景

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它是为了解决 HTTP 协议存在的一些问题而产生的。WebSocket 的产生背景主要包括以下几点:

HTTP 协议的局限性

HTTP 协议是一种请求-响应模型,客户端发起请求,服务端返回响应。这种模型存在一些问题,如无法主动推送数据给客户端,只能通过客户端轮询的方式获取数据。
HTTP 协议是无状态的,每次请求都需要重新建立连接,给服务器和客户端带来了不必要的开销。

HTTP 协议的局限性

HTTP 协议是一种请求-响应模型,客户端发起请求,服务端返回响应。这种模型存在一些问题:

1、无法主动推送数据给客户端,只能通过客户端轮询的方式获取数据,这会造成网络流量的浪费。
2、HTTP 协议是无状态的,每次请求都需要重新建立连接,给服务器和客户端带来了不必要的开销。
3、HTTP 协议头部信息较大,在移动网络环境下会造成较大的流量开销。
这些局限性使得 HTTP 协议难以满足实时交互、即时通信等应用的需求。

实时通信需求的增加

随着 Web 应用程序的复杂度提高,对实时交互、即时通讯等需求越来越强烈,例如:

聊天应用

需要即时的消息推送和响应。

多人游戏

需要客户端和服务端之间的实时数据交互。

股票行情

需要服务端能够实时推送最新的行情数据。
这些应用场景都需要一种更加合适的通信协议来满足实时性和双向通信的需求。

技术演进的驱动

HTML5 的发展为 WebSocket 的应用奠定了基础

HTML5 标准中正式定义了 WebSocket API,使浏览器能够原生支持 WebSocket 协议。
这为 WebSocket 在 Web 应用中的广泛应用奠定了技术基础。

服务端也开始支持 WebSocket 协议

如 Node.js 的 Socket.IO、Java 的 Spring WebSocket 等,使得 WebSocket 的应用变得更加广泛和成熟。
这些技术的进步为 WebSocket 协议的应用提供了必要的支持。

移动互联网时代的需求

移动互联网时代,用户对即时性和响应速度的要求越来越高,HTTP 协议的局限性越来越明显:

移动网络环境下,HTTP 协议的大量头部信息会造成较大的流量开销。
移动应用对实时交互的需求更加迫切,HTTP 协议难以满足。

WebSocket 协议可以提供更好的实时交互体验,因此在移动应用中得到了广泛应用。

websocket的特点

基于tcp实现的的长连接

理论上可以永久地维持连接,支持比传统轮询更长的轮询间隔,30、60秒甚至更长。websocket在没有消息的时候,会通过挂起请求的方式保持连接,到达时限的时候象征性地回个消息,以保持连接。

全双工

实现了服务端与客户端的互相通信。也因此,一旦有了新消息,服务端可以主动发起消息通知,解决了传统轮询只能服务端被动询问是否有新消息的难题。

单次握手

你可以理解为门票。持有门票的client才能与服务端通信。而单次握手的过程,便是服务端给客户端发门票的过程。通信的过程中,采取认票不认人的逻辑。

实时性

WebSocket 协议能够提供近乎实时的数据传输,延迟低于 100ms。
这使得 WebSocket 非常适合实时应用,如聊天应用、多人游戏等。

轻量化

WebSocket 协议的数据帧相比 HTTP 的请求/响应头部要小得多。
这在移动网络环境下可以大大减少流量开销,提高传输效率。

跨域支持

WebSocket 协议天生支持跨域通信,不受同源策略的限制。
这为构建分布式的实时应用提供了便利。

协议兼容

WebSocket 协议能够与 HTTP 协议很好地兼容,可以复用现有的 HTTP 基础设施。
这使得 WebSocket 的部署和集成更加简单。

常见应用场景

实时聊天应用

WebSocket 协议非常适合实时聊天应用,如即时通讯软件、在线客服系统等。
它可以提供低延迟的双向消息传递,支持即时的消息推送和接收。

多人游戏

WebSocket 协议能够支持多人游戏中的实时交互和状态同步。
如在线多人游戏、实时对战游戏等都可以很好地利用 WebSocket 技术。

实时数据推送

WebSocket 可以用于各种需要实时数据推送的应用场景,如股票行情、体育赛事直播等。
相比轮询 HTTP 请求,WebSocket 可以更高效地推送实时数据更新。

物联网(IoT)

WebSocket 协议适用于物联网设备之间的实时通信和控制。
通过 WebSocket 连接,物联网设备可以即时上报数据、接收命令和控制信号。

协同编辑

WebSocket 可以支持多人实时协作编辑文档、代码等内容的应用场景。
编辑者之间可以实时看到彼此的操作,协同编辑体验更好。

实时监控和报警

WebSocket 协议适用于需要实时监控和快速报警的场景,如工业设备监控、网站性能监控等。
监控数据可以通过 WebSocket 实时推送到客户端,快速响应异常情况。

简单示例

Node.js 和 Socket.IO实现的多人在线棋牌游戏

首先,我们需要一个服务端代码:

// server.js
const express = require('express');
const http = require('http');
const socketIO = require('socket.io');const app = express();
const server = http.createServer(app);
const io = socketIO(server);// 游戏房间管理
const rooms = {};// 客户端连接事件处理
io.on('connection', (socket) => {console.log('用户连接:', socket.id);// 创建房间socket.on('create_room', (roomName) => {rooms[roomName] = { players: [], state: 'waiting' };socket.join(roomName);socket.emit('room_created', roomName);});// 加入房间socket.on('join_room', (roomName) => {if (rooms[roomName]) {rooms[roomName].players.push(socket.id);socket.join(roomName);io.to(roomName).emit('player_joined', rooms[roomName].players);if (rooms[roomName].players.length === 2) {rooms[roomName].state = 'playing';io.to(roomName).emit('game_started');}} else {socket.emit('room_not_found');}});// 下棋socket.on('make_move', (roomName, position) => {if (rooms[roomName]) {io.to(roomName).emit('move_made', socket.id, position);}});// 断开连接socket.on('disconnect', () => {console.log('用户断开:', socket.id);// 处理用户断开连接的逻辑});
});server.listen(3000, () => {console.log('Server started on port 3000');
});

这个服务端代码实现了基本的房间创建、玩家加入、游戏开始和下棋等逻辑。

接下来,我们需要一个客户端代码:

<!-- client.html -->
<!DOCTYPE html>
<html>
<head><title>在线多人游戏</title><script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
</head>
<body><h1>在线多人游戏</h1><button id="createRoom">创建房间</button><input type="text" id="roomName" placeholder="输入房间名" /><button id="joinRoom">加入房间</button><div id="gameBoard"></div><script>const socket = io('http://localhost:3000');// 创建房间document.getElementById('createRoom').addEventListener('click', () => {const roomName = document.getElementById('roomName').value;socket.emit('create_room', roomName);});// 加入房间document.getElementById('joinRoom').addEventListener('click', () => {const roomName = document.getElementById('roomName').value;socket.emit('join_room', roomName);});// 处理游戏事件socket.on('room_created', (roomName) => {console.log('房间创建成功:', roomName);});socket.on('room_not_found', () => {console.log('房间不存在');});socket.on('player_joined', (players) => {console.log('有玩家加入:', players);});socket.on('game_started', () => {console.log('游戏开始');});socket.on('move_made', (playerId, position) => {console.log('玩家', playerId, '下了一步', position);});</script>
</body>
</html>

这个客户端代码实现了基本的房间创建、加入房间和接收游戏事件的逻辑。

通过这个示例,你可以看到 WebSocket 协议在实现在线多人游戏中的应用。服务端负责管理房间和游戏逻辑,客户端负责与服务端交互和显示游戏状态。这种基于 WebSocket 的实时双向通信方式非常适合实现这类游戏应用。

基于 Python 和 React 实现的 WebSocket 多人实时对战

服务端 (Python + WebSocket)

我们将使用 Python 的 websocket-server 库来实现服务端的 WebSocket 处理逻辑。

# server.py
import json
from websocket_server import WebsocketServer# 游戏房间管理
rooms = {}# 新客户端连接
def new_client(client, server):print(f"新客户端连接: {client['address']}")# 客户端断开连接
def client_left(client, server):print(f"客户端断开: {client['address']}")# 处理用户断开连接的逻辑# 接收客户端消息
def message_received(client, server, message):data = json.loads(message)action = data['action']if action == 'create_room':room_name = data['room_name']rooms[room_name] = {'players': [client['id']], 'state': 'waiting'}server.send_message(client, json.dumps({'action': 'room_created', 'room_name': room_name}))elif action == 'join_room':room_name = data['room_name']if room_name in rooms:rooms[room_name]['players'].append(client['id'])server.send_message_to_all(json.dumps({'action': 'player_joined', 'room_name': room_name, 'players': rooms[room_name]['players']}))if len(rooms[room_name]['players']) == 2:rooms[room_name]['state'] = 'playing'server.send_message_to_all(json.dumps({'action': 'game_started', 'room_name': room_name}))else:server.send_message(client, json.dumps({'action': 'room_not_found'}))elif action == 'make_move':room_name = data['room_name']position = data['position']server.send_message_to_all(json.dumps({'action': 'move_made', 'room_name': room_name, 'player_id': client['id'], 'position': position}))server = WebsocketServer(host='localhost', port=8000, on_new_client=new_client, on_client_left=client_left, on_message=message_received)
server.run_forever()

客户端 (React + WebSocket)

我们将使用 React 和 socket.io-client 库来实现客户端的 WebSocket 交互。

// App.js
import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';function App() {const [socket, setSocket] = useState(null);const [roomName, setRoomName] = useState('');const [players, setPlayers] = useState([]);const [gameStarted, setGameStarted] = useState(false);useEffect(() => {const newSocket = io('ws://localhost:8000');setSocket(newSocket);return () => newSocket.disconnect();}, []);const createRoom = () => {socket.emit('create_room', roomName);};const joinRoom = () => {socket.emit('join_room', roomName);};const makeMove = (position) => {socket.emit('make_move', { room_name: roomName, position });};useEffect(() => {if (socket) {socket.on('room_created', (data) => {console.log('Room created:', data.room_name);});socket.on('room_not_found', () => {console.log('Room not found');});socket.on('player_joined', (data) => {setPlayers(data.players);});socket.on('game_started', () => {setGameStarted(true);});socket.on('move_made', (data) => {console.log(`Player ${data.player_id} made a move at ${data.position}`);});}}, [socket]);return (<div><h1>WebSocket 多人实时对战</h1><inputtype="text"placeholder="Room Name"value={roomName}onChange={(e) => setRoomName(e.target.value)}/><button onClick={createRoom}>Create Room</button><button onClick={joinRoom}>Join Room</button>{gameStarted && (<div><h2>Game Started!</h2><p>Players: {players.join(', ')}</p><button onClick={() => makeMove({ x: 0, y: 0 })}>Move</button></div>)}</div>);
}export default App;

在这个示例中,服务端使用 Python 的 websocket-server 库来管理 WebSocket 连接和游戏逻辑。客户端则使用 React 和 socket.io-client 库来与服务端进行 WebSocket 通信,实现房间创建、加入房间和下棋等功能。

值得注意的是,这只是一个基本的示例,在实际开发中,你需要考虑更多的功能和优化,如游戏规则实现、错误处理、性能优化等。同时,你还需要处理客户端断开连接的情况,以及如何在客户端渲染游戏画面等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

等级保护测评与风险评估:构建网络安全的双重保障

# 等级保护测评与风险评估&#xff1a;构建网络安全的双重保障 在网络信息技术飞速发展的今天&#xff0c;网络安全问题日益成为社会关注的焦点。等级保护测评和风险评估作为网络安全管理的两个重要环节&#xff0c;对于确保信息系统的安全稳定运行具有重要意义。本文将探讨等级…

Stage #15深度解析:十六进制编码在XSS绕过中的应用

Stage #15深度解析&#xff1a;十六进制编码在XSS绕过中的应用 在网络安全领域&#xff0c;跨站脚本攻击&#xff08;XSS&#xff09;是一种常见的网络攻击手段。随着Web应用安全防护措施的不断完善&#xff0c;攻击者需要更高级的技术来绕过这些防护。本文将详细介绍如何利用…

1782java英语陪学记词系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java英语陪学记词系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

AI大底座核心平台:百度百舸AI异构计算平台(AI IaaS)与AI中台(AI PaaS)

AI大底座正是整合了以上端到端全要素技术能力&#xff0c;将基础架构IaaS与应用平台PaaS能力深度融合&#xff0c;面向企业和产业AI生 产与应用的全生命周期提供完整解决方案。 百舸AI异构计算平台是AI IaaS层的核心平台&#xff0c;包括AI计算、AI存储、AI加速、AI容器四层套件…

win磁盘映射到linux

有时虚拟机磁盘不够或文件想存在本地但使用linux环境&#xff0c;可以使用磁盘映射 1.windows磁盘映射&#xff0c;指定文件win_share进行文件共享&#xff0c;右键属性共享 2.linux 新建映射目录win_share 3.在linux进行挂载 sudo mount -t cifs //win7ip地址/win_share /hom…

【k8s的三种探针】

一、探针类型 作用&#xff1a;容器内应用的监测机制&#xff0c;根据不同的探针来判断容器应用当前的状态。 k8s 有三种类型的探针&#xff1a;StartupProbe(启动探针)、LivenessProbe(存活探针)、ReadinessProbe(就绪探针)。它们可以同时存在&#xff0c;但如果有StartupPro…

shell(一)

shell 既是脚本语言又是应用程序 查看自己linux系统的默认解析&#xff1a;echo $SHELL 创建第一个shell 文件 touch 01.sh编辑 vi 01.sh01.sh 文件内容 #!/bin/bash echo felicia保存 按Esc 然后输入:wq 定义以开头&#xff1a;#!/bin/bash #!用来声明脚本由什么shell解释…

idea maven 执行 控制台乱码

这是没加出现的问题 上方案

【HTTP系列】TCP/IP协议

文章目录 一、是什么二、划分五层体系应用层传输层网络层数据链路层物理层 四层体系 三、总结参考文献 一、是什么 TCP/IP&#xff0c;传输控制协议/网际协议&#xff0c;是指能够在多个不同网络间实现信息传输的协议簇 TCP&#xff08;传输控制协议&#xff09; 一种面向连…

【YOLOv5/v7改进系列】替换上采样层为Dysample

一、导言 介绍了一种名为DySample的超轻量级且高效的动态上采样器。DySample旨在解决当前动态上采样技术如CARAFE、FADE和SAPA虽然性能提升显著但带来大量计算负担的问题&#xff0c;这些问题主要来源于动态卷积的时间消耗以及用于生成动态核的额外子网络。此外&#xff0c;FA…

STC90C51驱动LCD1602、LCD12864、OLED

主控芯片&#xff08;STC90C516RDPG5151028&#xff09;介绍 ROM64K,RAM1280字节&#xff0c;40Pin&#xff0c;3个定时器&#xff0c;1个串口&#xff0c;8个中断源&#xff08;分别是&#xff1a;外部中断0(INTO)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定…

系统化自学Python的实用指南

目录 一、理解Python与设定目标 二、搭建学习环境与基础准备 三、入门学习阶段 四、中级进阶阶段 五、项目实践与持续深化 六、持续学习与拓展 一、理解Python与设定目标 Python概述&#xff1a;详细介绍Python的历史沿革、设计理念、主要特点&#xff08;如易读、易维护…

pytest构建和测试FastAPI CURD API

文章目录 概述目标FASTAPI 介绍CRUD API 项目设置freezepipreqs 代码介绍run APIpytest测试F&Q1.执行uvicorn app.main:app --host localhost --port 8000 --reload 报错 zsh: /usr/local/bin/uvicorn: bad interpreter2.生成requirement.txt时&#xff0c;pip3 list pipre…

C语言printf( ) 函数有哪些参数?

一、问题 printf( ) 函数的作⽤是向终端输出若⼲个任意类型的数据&#xff0c;此函数由格式控制部分和输出表列两部分组成&#xff0c;格式控制部分⼜由“&#xff05;”和格式字符串组成&#xff0c;那么&#xff0c;此函数格式字符串部分有哪些参数呢&#xff1f; 二、解答 …

Frida 学习之 messages

目录 一、消息发送 二、环境准备 三、从目标进程中发消息 四、在目标进程中接收消息 五、在目标进程中以阻塞方式接收消息 官方链接&#xff1a;Messages | Frida • A world-class dynamic instrumentation toolkit 参考链接&#xff1a;Frida官方手册 - 消息发送_frida…

Git操作--如何将本地文件夹push到远程新建的仓库中

一、从命令行创建一个新的仓库 1、创建一个说明文件 touch README.md 2、首先使该目录成为git可以管理的目录 git init 3、添加所有文件到本地暂存区 git add . #&#xff08;不要忘了后面的点"."&#xff0c;表示所有文件及目录&#xff09; # git add README…

v-model的工作原理是什么

v-model在Vue.js中是一个非常重要的指令&#xff0c;它实现了表单输入与应用状态&#xff08;data&#xff09;之间的双向绑定。以下是v-model的工作原理&#xff0c;我会尽量以清晰的方式分点表示和归纳&#xff1a; 本质&#xff1a; v-model本质上是一个语法糖&#xff0c…

C语言 RTC时间(年月日时分秒) 和 时间戳 互相转换

一、介绍 在C语言中&#xff0c;将年月日时分秒转换为时间戳&#xff08;Unix时间戳&#xff0c;即从1970年1月1日00:00:00 UTC到现在的秒数&#xff09;通常需要使用struct tm结构体和timegm或mktime函数。&#xff08;注意&#xff0c;mktime函数假设struct tm是本地时间&…

Python语法详解module4(函数)

目录 一、函数基础1. 函数的概念和作用2. 函数的定义和调用3. 参数传递 二、返回值和文档字符串返回值的概念和用法1. 返回值的概念2. 使用 return 关键字返回值&#xff1a;3. 多个返回值的情况&#xff1a; 文档字符串&#xff08;docstring&#xff09;的作用和使用方法1. 文…

力扣1610.可见点的最大数目

力扣1610.可见点的最大数目 把所有极角算出来 atan2(x,y)函数 返回值为弧度(带π) 存入数组并排序 断链成环 再开n个空间 d[ni] d[i] 2*π 在极角数组中找到一段极差<k的最大数目的区间(滑窗) class Solution {vector<double> d;double k;public:int visibleP…