iOS WebSocket通信实战:SIOSocket应用指南

打印 上一主题 下一主题

主题 906|帖子 906|积分 2718

本文另有配套的精品资源,点击获取  

  简介:WebSocket协议在iOS开辟中用于实现客户端与服务器之间的持久及时通信。SIOSocket是实用于iOS和Mac OS X的Objective-C库,它基于Socket.IO,简化了WebSocket的使用,同时提供了自动重连、心跳检测等高级特性。本指南将详细先容怎样在iOS应用中使用SIOSocket来创建WebSocket客户端,包括初始化毗连、变乱监听、消息发送接收、毗连管理、房间和定名空间操纵、心跳检测以及自界说配置等关键知识点。通过示例代码和SIOSocket源码的分析,学习者可以掌握将WebSocket集成到iOS应用中,实现高效及时交互的完整流程。
1. WebSocket协议简介及在iOS中的应用

1.1 WebSocket协议的根本概念

  WebSocket是一种网络通信协议,提供全双工通信机制,允许服务器和客户端之间在单个TCP毗连上举行双向数据传输。这种特性使得WebSocket非常得当需要快速交换数据的场景,如及时聊天、在线游戏或交互式内容更新。
1.2 WebSocket在iOS开辟中的重要性

  随着移动互联网的发展,iOS应用也需要及时功能,而传统的HTTP协议由于其请求-相应模型,无法满足这一需求。通过WebSocket协议,iOS开辟者可以大概实现及时的数据通信,极大地提升了用户体验。
1.3 实现WebSocket的iOS客户端

  在iOS中,开辟者可以通过原生API或者第三方库如SIOSocket来实现WebSocket客户端。SIOSocket不但提供了简朴的API,还支持多种消息处理机制,易于集成到iOS项目中。接下来的章节,我们将详细探究SIOSocket库的特性、优势及其在iOS应用中的具体应用。
2. SIOSocket库的特点和优势

2.1 SIOSocket库的计划理念

2.1.1 架构计划与性能考量

  SIOSocket库在计划时遵循了简洁和高效的原则。在架构层面,其采用了模块化的计划方法,将网络通信的核心功能封装在一个轻量级的库中,通过清晰界说的API接口与外界交互。为了确保性能,库内部实现了非壅闭IO和变乱驱动的处理机制,这显著提升了处理并发毗连的能力。
  在计划时,性能考量主要集中在以下几个方面: - 内存使用: 对于内存的使用举行了优化,尤其是对于消息缓冲和对象生命周期管理,以减少内存分配和回收带来的性能损耗。 - CPU占用: 实现了高效的数据处理算法,包括数据的序列化和反序列化,确保CPU的占用率保持在合理范围内,避免不必要的资源浪费。 - 网络IO: 利用现代操纵体系的IO复用技术,如select、epoll或kqueue,实现了高效的网络IO处理,减少了对于体系资源的依赖,同时进步了处理大量并发毗连的能力。
2.1.2 跨平台支持及版本兼容性

  跨平台支持是SIOSocket库的另一个计划亮点。该库支持从iOS到macOS,再到其他主流操纵体系,如Windows、Linux以及Android。为了实现跨平台的兼容性,库内部使用了抽象层的概念,对底层网络操纵举行了封装,使得在不同的操纵体系中都能以雷同的方式调用网络通信的相干功能。
  版本兼容性是通过遵循语义化版本控制原则来实现的。SIOSocket库向后兼容性保持得很好,这意味着在新版本中,旧版本的API仍然可用,确保了应用在升级库时的平滑过渡。为了降低升级的门槛,每当发布新版本时,库的文档和迁移指南都会更新,为开辟者提供详细的信息和引导。
2.2 SIOSocket与其它iOS WebSocket库的比较

2.2.1 功能对比

  SIOSocket在功能上与其他iOS WebSocket库举行了全面的比较,特殊是在毗连管理、消息通报机制以及提供的工具和接口方面。SIOSocket库提供了以下独特的功能点:


  • 毗连断开重试机制: 可以大概在网络条件不稳固时自动重连,并且支持重试次数和时间间隔的自界说配置。
  • 消息发送确认: 提供了消息发送确认机制,确保每个消息都得到服务器端的正确处理,并且在失败时可以举行重发。
  • 扩展变乱处理: 允许开辟者自界说变乱和处理逻辑,通过变乱监听器来扩展库的功能。
2.2.2 性能测试与评估

  性能测试与评估是一个体系性的工程,需要在不同环境、不同负载下举行。SIOSocket的性能测试通常包括了基准测试、压力测试和稳固性测试。基准测试可以评估库的理论上的性能极限,而压力测试则用来模拟高负载下的行为体现。稳固性测试则是长时间运行以检验库的可靠性和内存泄漏等问题。
  测试结果表明,SIOSocket在高并发毗连和大数据传输场景下依然保持较高的性能水平。其性能优化部门得益于底层网络库的高效实现,以及在消息编解码和内存管理方面的精心计划。
2.2.3 社区和生态体系支持

  SIOSocket不但在技术上具有优势,同时,在社区支持和生态体系方面也有显著的体现。该库有一个活跃的社区,开辟者可以在社区中提问、分享履历、到场讨论。此外,社区中还包括了一系列的插件和扩展,可以资助开辟者在现有的库基础上快速增长新的功能。
  SIOSocket的官方文档详细、清晰且易于理解,为开辟者提供了丰富的学习资源,包括API参考、使用教程以及常见问题解答。社区定期组织线上和线下的研讨会,分享最佳实践,推动技术的传播和应用。
  在此基础上,SIOSocket的开辟者们持续关注用户反馈,对用户提出的问题和发起都给予高度的器重,并且努力将这些反馈转化为库的改进和更新。这样的社区和生态体系支持,为SIOSocket的用户带来了更好的使用体验和技术支持。
3. SIOSocket初始化和毗连方法

3.1 SIOSocket的环境搭建与配置

3.1.1 快速开始:创建和配置项目

  初始化一个使用 SIOSocket 的 iOS 项目非常直接。起首,确保你的开辟环境是最新版本的 Xcode,并且你有最新的 iOS SDK。接下来,创建一个新的项目,并按照以下步骤举行配置:

  • 打开 Xcode,选择“File” > “New” > “Project”来创建一个新项目。
  • 选择符合的模板,例如“Single View App”,然后点击“Next”。
  • 在项目设置界面,填写项目名称、Team、Organization Name 和 Bundle Identifier。对于 Language 选项,选择 Swift 或 Objective-C。
  • 选择项目存储的位置,然后点击“Create”。
  完成项目创建后,你需要在项目中集成 SIOSocket 库。如果你选择使用 CocoaPods,可以在项目的 Podfile 中添加如下代码:
  1. pod 'SIOSocket', '~> 2.0.0'
复制代码
然后运行  pod install  来安装依赖。之后,使用新生成的  .xcworkspace  文件打开你的项目,以确保库文件被正确链接。
3.1.2 依赖项管理与版本控制

  在任何项目中,依赖项的管理是至关重要的,特殊是当你使用第三方库时。使用 CocoaPods 不但可以简化依赖管理过程,还能资助你追踪和更新库的版本。
  你可以通过以下步骤管理依赖项:

  • 在项目的根目次下创建一个 Podfile 文件,界说你的项目依赖。
  • 运行  pod install  来安装依赖项。这将生成一个  .xcworkspace  文件,你应该使用它来打开你的项目,而不是原始的  .xcodeproj  文件。
  • 当需要更新依赖库时,可以运行  pod update  命令。
  为了版本控制,确保将所有依赖项的版本锁定在你的  Podfile.lock  文件中。这样,其他开辟者和部署环境在运行  pod install  时会得到雷同的依赖项版本。
  1. platform :ios, '10.0'use_frameworks!target 'YourProjectName' do  pod 'SIOSocket', '~> 2.0.0'
  2. end
复制代码
3.2 SIOSocket毗连建立流程

3.2.1 初始化实例与配置参数

  在使用 SIOSocket 前,起首需要初始化库并配置参数。以下是一个初始化实例的代码示例:
  1. import SIOSocket
  2. let socketConfiguration = SIOSocket.Configuration(url: "ws://***/socket")
  3. let socket = SIOSocket(socketConfiguration: socketConfiguration)
复制代码
在这个例子中,  SIOSocket.Configuration  对象被用来指定 WebSocket 服务器的 URL。创建配置实例后,使用这个配置实例来创建一个  SIOSocket  实例。
  配置参数可以包括重连计谋、心跳间隔、是否使用安全毗连(wss)等。下面是一个带有高级配置参数的示例:
  1. let advancedSocketConfiguration = SIOSocket.Configuration(
  2.     url: "wss://***/socket",
  3.     reconnectInterval: 5, // 重连间隔5秒
  4.     heartBeatInterval: 10, // 心跳间隔10秒
  5.     useSecureConnection: true // 启用安全连接
  6. )
  7. let advancedSocket = SIOSocket(socketConfiguration: advancedSocketConfiguration)
复制代码
3.2.2 毗连服务器的方式与参数

  在配置完 SIOSocket 实例后,下一步是毗连到 WebSocket 服务器。SIOSocket 库提供了多种毗连方式和参数,以便更好地控制毗连过程。
  根本毗连方法如下:
  1. do {
  2.     try socket.connect()
  3. } catch let error {
  4.     print("连接失败: \(error)")
  5. }
复制代码
  connect()  方法是异步的,当毗连乐成或失败时,会触发相应的变乱。你可以通过添加回调函数来处理这些变乱。
  对于更复杂的毗连需求,可以通过配置毗连参数来实现。例如,如果你想在建立毗连前发送一些自界说头部信息,可以这样做:
  1. let headers: [String: String] = ["Authorization": "Bearer yourtoken"]
  2. socket.connect(headers: headers)
复制代码
3.2.3 毗连失败与重试机制

  毗连失败时,SIOSocket 提供了重试机制来增长毗连的鲁棒性。你可以在配置中指定重连计谋,如重连间隔和最大重连次数:
  1. let reconnectConfig = SIOSocket.Configuration(
  2.     url: "ws://***/socket",
  3.     reconnectPolicy: .retryOnFailure(maxAttempts: 5, delay: 3) // 最多重试5次,每次间隔3秒
  4. )
  5. let socketWithRetry = SIOSocket(socketConfiguration: reconnectConfig)
复制代码
这种配置方式确保了在毗连失败时,步伐将等待3秒后实验重新毗连,直到到达5次实验限制。
3.3 完整代码展示与逻辑分析

  下面是一个完整的初始化和毗连流程代码示例:
  1. import UIKit
  2. import SIOSocket
  3. class WebSocketManager {
  4.     private var socket: SIOSocket?
  5.     init() {
  6.         self.setupSocket()
  7.     }
  8.     func setupSocket() {
  9.         let configuration = SIOSocket.Configuration(
  10.             url: "wss://***/socket",
  11.             reconnectPolicy: .retryOnFailure(maxAttempts: 5, delay: 3),
  12.             headers: ["Authorization": "Bearer yourtoken"]
  13.         )
  14.         socket = SIOSocket(socketConfiguration: configuration)
  15.         socket?.onOpen = { [weak self] socket in
  16.             print("连接成功")
  17.             // 连接成功后的操作
  18.         }
  19.         socket?.onClose = { [weak self] code, reason in
  20.             print("连接关闭: \(code), \(reason)")
  21.             // 连接关闭后的处理
  22.         }
  23.         socket?.onError = { [weak self] error in
  24.             print("连接错误: \(error)")
  25.             // 错误处理
  26.         }
  27.         do {
  28.             try socket?.connect()
  29.         } catch {
  30.             print("连接失败: \(error)")
  31.         }
  32.     }
  33. }
复制代码
此段代码展示了怎样配置 SIOSocket 实例并处理毗连过程中的各种变乱。  onOpen  ,  onClose  , 和  onError  回调函数分别用于处理毗连乐成、关闭和错误情况。这些处理函数中应当包罗对应的业务逻辑,以确保步伐的正常运行。
  此外,通过  try  和  catch  非常处理可以捕获毗连时大概发生的错误,并给出相应的提示信息。  [weak self]  的使用是为了避免循环引用,确保在回调函数中可以大概安全地引用  WebSocketManager  实例。
  这段代码为基于 SIOSocket 库的 WebSocket 通信提供了一个基础框架,实用于大多数基于 iOS 的及时通信应用场景。
4. 变乱监听及处理机制

  变乱监听和处理是WebSocket通信中至关重要的一环,因为它直接关系到应用怎样相应服务器发来的各种状态变动和消息。在SIOSocket库中,变乱处理模型的计划充分考虑了易用性和灵活性,允许开辟者监听多种变乱并作出相应的处理。本章将深入探究SIOSocket的变乱监听及处理机制,并提供性能优化技巧和最佳实践。
4.1 SIOSocket变乱处理模型

4.1.1 常见变乱类型与回调函数

  SIOSocket支持多种变乱类型,每个变乱类型都对应特定的回调函数。开辟者可以根据不同的应用场景注册相应的监听器来处理这些变乱。


  •   open  : 当WebSocket乐成毗连后触发。
  •   message  : 当接收到服务器发送的消息时触发。
  •   error  : 当发生错误时触发,例如毗连失败。
  •   close  : 当WebSocket毗连被关闭时触发。
  下面的代码示例展示了怎样在SIOSocket中注册和使用这些变乱的监听器:
  1. let socket = SIOSocket(url: "wss://***")
  2. socket.onOpen = { (ws) in
  3.     print("连接已打开")
  4. }
  5. socket.onMessage = { (ws, message) in
  6.     print("接收到消息: \(message)")
  7. }
  8. socket.onError = { (ws, error) in
  9.     print("发生错误: \(error.localizedDescription)")
  10. }
  11. socket.onClose = { (ws, code, reason) in
  12.     print("连接已关闭, 代码: \(code), 原因: \(reason ?? "未知")")
  13. }
  14. do {
  15.     try socket.connect()
  16. } catch {
  17.     print("连接失败: \(error.localizedDescription)")
  18. }
复制代码
4.1.2 回调实行次序与异步处理

  在多线程环境下,变乱回调的实行次序大概会受到异步操纵的影响。因此,SIOSocket的回调函数是异步实行的,并且被计划为尽大概地减少壅闭和进步相应速率。
  在Swift中,异步函数通常通过  async  和  await  关键字调用,但SIOSocket的变乱监听器中使用的是闭包方式来处理异步回调。这意味着,回调函数的实行并不会壅闭主线程,可以在得当的时候实行复杂的逻辑而不需要担心UI卡顿等问题。
  1. socket.onMessage = { [weak self] (ws, message) in
  2.     DispatchQueue.main.async {
  3.         // 更新UI等操作,可以在这里进行
  4.     }
  5. }
复制代码
这段代码展示了怎样在变乱回调中安全地更新UI,注意使用  [weak self]  来避免循环引用的问题。
4.2 自界说变乱的处理与优化

  虽然SIOSocket已经提供了一系列变乱监听器,但在复杂的应用中大概需要更多的自界说变乱处理。接下来我们将探索怎样实现自界说变乱监听器,并分享一些性能优化技巧。
4.2.1 实现自界说变乱监听器

  在某些场景中,开辟者大概需要监听一些非尺度的变乱或者基于多个变乱的组合逻辑。实现自界说变乱监听器是一个强大的方法来增强应用的交互性和用户体验。
  1. extension SIOSocket {
  2.     public func addCustomEventListener(_ event: String, handler: @escaping (Any) -> Void) {
  3.         // 这里可以实现自定义事件的逻辑,例如:
  4.         // 如果需要结合多个事件来触发自定义事件,可以在这里编写代码逻辑
  5.     }
  6. }
复制代码
4.2.2 性能优化技巧与最佳实践

  在处理大量变乱时,性能优化显得尤为重要。以下是一些根本的优化技巧:

  •    变乱去抖动 : 对于高频触发的变乱(如  message  变乱),在回调函数中引入去抖动机制,减少不必要的处理。
  •    线程管理 : 确保回调函数实行在正确的线程上,避免UI线程壅闭。
  •    资源清理 : 在不再需要监听器时,应该及时移除它以避免内存泄漏。
  1. socket.onMessage = { (ws, message) in
  2.     // 应用去抖动逻辑
  3.     DebounceQueue.add { [weak self] in
  4.         // 安全执行回调
  5.         self?.handleMessage(message)
  6.     }
  7. }
  8. // 确保移除监听器时执行资源清理
  9. socket.removeMessageListener()
复制代码
通过上述代码,我们演示了怎样通过自界说变乱监听器处理复杂的变乱,并给出了根本的性能优化发起。实际应用中,开辟者应根据具体需求和应用场景来调整和优化变乱处理逻辑。
5. 发送和接收消息的具体实现

5.1 SIOSocket的数据帧与消息结构

5.1.1 消息类型与编码方式

  SIOSocket 传输数据时使用基于 WebSocket 协议的数据帧格式。WebSocket 界说了多种消息类型,其中包括文本消息、二进制消息和控制消息。文本消息以 UTF-8 编码,得当发送文本数据,而二进制消息允许发送任意类型的文件数据或二进制数据。控制消息包括心跳Ping和心跳Pong,用于维护毗连的活跃性。
  在使用 SIOSocket 时,开辟者一般不需要直接处理帧级别的细节,因为 SIOSocket 库提供了更高条理的抽象。但了解这些细节对于理解怎样优化传输和处理边缘情况是有益的。特殊是,文本消息和二进制消息的编码方式对于数据传输的效率和大小有着直接影响。
5.1.2 消息的发送与接收流程

  发送消息时,开辟者调用 SIOSocket 实例提供的  sendMessage()  方法,将需要发送的数据作为参数通报给该方法。库内部会将数据封装到一个消息帧中,并将其转换为网络字节省发送到服务器。
  1. // 代码示例:发送消息
  2. socket.sendMessage("Hello, World!") // 发送文本消息
  3. socket.sendBinary(data: binaryData) // 发送二进制数据
复制代码
在接收消息的过程中,SIOSocket 库会监听网络毗连,并将接收到的字节省解析为数据帧。当数据帧被正确解析后,库会触发一个变乱,变乱监听器中的回调函数将被调用,并将消息作为参数通报给回调函数。
  1. // 代码示例:接收消息
  2. socket.onMessageReceived = { message in
  3.     print("Received: \(message)")
  4. }
复制代码
理解消息类型和处理流程对于开辟者来说至关重要,因为这将影响到应用怎样发送和展示数据,也会影响到应用的整体性能。
5.2 高级消息处理技巧

5.2.1 消息分片与重组

  由于网络带宽的限制或数据量巨大,往往需要将消息分片发送。这要求接收端能正确重组这些消息碎片,恢复出完整的信息。SIOSocket 提供了分片机制,允许开辟者将大数据量消息分成多个小部门,通过编号和标志来包管消息的完整性。
  1. // 代码示例:发送分片消息
  2. for i in 0..<totalFragments {
  3.     let fragment = data.substring(with: Range(i..<min(i + fragmentSize, data.count)))
  4.     let frame = WebSocketDataFrame.fragment(data: fragment, isFinal: i == totalFragments - 1)
  5.     socket.sendDataFrame(frame)
  6. }
复制代码
在接收端,SIOSocket 处理库会自动处理分片,并在所有片段到达后重组消息:
  1. // 代码示例:接收分片消息的回调函数
  2. socket.onDataFrameReceived = { frame in
  3.     // 重组消息逻辑
  4.     // ...
  5. }
复制代码
开辟者需要确保实现的逻辑中包罗对于消息分片的检测,错误处理和确保消息次序性的机制,以避免数据在传输过程中丢失或乱序。
5.2.2 大数据传输与内存管理

  在处理大数据传输时,内存管理是关键。开辟者需谨慎处理内存斲丧,避免应用步伐因内存不足而崩溃。在 Swift 中,可以使用自动引用计数(ARC)来管理内存,但仍然需要关注循环引用和闭包捕获的问题。
  1. // 代码示例:内存管理中避免循环引用
  2. class MessageReceiver {
  3.     weak var delegate: MessageDelegate?
  4.     func processLargeMessage(_ message: LargeMessage) {
  5.         delegate?.messageReceived(message)
  6.     }
  7. }
复制代码
别的,可以采用流式处理来渐渐读取和处理数据,从而减少内存峰值。流式处理将数据逐块读入内存,而不是一次性加载整个数据集。
  1. // 代码示例:流式处理大数据
  2. func streamLargeData(_ data: InputStream) {
  3.     while let chunk = data.readSomeData() {
  4.         // 处理数据块
  5.         // ...
  6.     }
  7. }
复制代码
通过合理使用内存和流式处理大数据,可以有用提升应用处理消息时的性能和稳固性。
6. 毗连管理与通信优化

  在任何及时通信应用中,毗连的稳固性与通信效率都是至关重要的。第六章将侧重讨论怎样通过SIOSocket库举行高效稳固的毗连管理和通信优化。
6.1 自动重连与心跳检测机制

  在及时通信应用中,网络的不稳固性和客户端的意外断开是常见的问题。为了包管通信的连续性和稳固性,SIOSocket库提供了自动重连机制和心跳检测功能。
6.1.1 毗连稳固性保障计谋

  为了实现毗连的稳固性,SIOSocket库在底层封装了自动重连的计谋。当毗连意外断开时,客户端会根据预设的重连间隔实验重新毗连服务器。
  1. let socket = SIOSocket(host: "your-wss-url", port: 8080)
  2. // 设置重连间隔
  3. socket.reconnectionInterval = 3 // seconds
  4. // 开启自动重连
  5. socket.reconnectAutomatically = true
复制代码
以上代码段展示了怎样配置SIOSocket实例的重连间隔,并启用自动重连功能。当毗连断开时,客户端会每隔3秒实验重新毗连服务器。
6.1.2 心跳检测的作用与实现

  心跳检测是及时通信中的另一种重要机制,它资助服务器检测并确认客户端是否仍然在线,从而避免资源的无效占用。
  SIOSocket允许开辟者设置心跳检测的时间间隔:
  1. socket.heartbeatInterval = 10 // seconds
复制代码
设置心跳间隔为10秒,意味着如果在这个时间间隔内,客户端没有接收到任何数据,它将向服务器发送心跳包,以确认毗连状态。
6.2 房间和定名空间的概念及应用

  在复杂的及时通信体系中,房间和定名空间是实现有用管理和通信隔离的重要概念。
6.2.1 房间与定名空间在通信中的脚色

  房间提供了一个逻辑上的概念,允很多个客户端到场到同一通信频道,共享消息。而定名空间则是一个更高条理的概念,它允许在同一应用中创建多个房间,并将房间分组。
  在SIOSocket中,可以这样创建一个房间:
  1. let room = try! socket.createRoom("chat-room")
复制代码
6.2.2 高级通信模式与实践案例

  通过房间和定名空间,开辟者可以构建出高级的通信模式,例如在聊天应用中,用户可以到场不同的聊天室,每个聊天室可以有不同的权限和消息处理规则。
  1. // 加入房间并监听事件
  2. room.join()
  3. room.on(message: { (message) in
  4.     print("Received message: \(message)")
  5. })
复制代码
在上面的代码段中,我们创建了一个名为"chat-room"的聊天室,并监听了该房间中的消息。每当收到消息时,都会打印出来。
  在实践中,房间和定名空间可以用于构建群组聊天、及时游戏、共享白板等多种及时通信场景,极大地丰富了应用的功能性。
  在本章中,我们先容了SIOSocket中的毗连管理与通信优化计谋,包括自动重连机制、心跳检测、房间和定名空间的概念及其应用。通过这些高级特性,开辟者可以构建更加稳固和高效的及时通信体系。在下一章中,我们将探索SIOSocket的自界说配置选项和错误处理计谋。
   本文另有配套的精品资源,点击获取  

  简介:WebSocket协议在iOS开辟中用于实现客户端与服务器之间的持久及时通信。SIOSocket是实用于iOS和Mac OS X的Objective-C库,它基于Socket.IO,简化了WebSocket的使用,同时提供了自动重连、心跳检测等高级特性。本指南将详细先容怎样在iOS应用中使用SIOSocket来创建WebSocket客户端,包括初始化毗连、变乱监听、消息发送接收、毗连管理、房间和定名空间操纵、心跳检测以及自界说配置等关键知识点。通过示例代码和SIOSocket源码的分析,学习者可以掌握将WebSocket集成到iOS应用中,实现高效及时交互的完整流程。
   本文另有配套的精品资源,点击获取  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表