首页 iOS.& Swift Books 服务器端迅速与蒸气

30
WebSockets. 由洛根赖特写的

WebSockets.,如HTTP,定义了用于两个设备之间通信的协议。与HTTP不同,WebSocket协议专为实时通信而设计。 WebSockets可以是聊天或其他需要实时行为的其他功能的重要选择。 vapor提供了一个简洁的API来创建WebSocket服务器或客户端。本章侧重于构建基本服务器。

在本章中,您将构建一个简单的客户端 - 服务器应用程序,允许用户与其他用户共享触摸,并在实时查看其自己的设备上的触摸。

工具

测试WebSockets可能有点棘手,因为它们可以发送/接收多个消息。这使得使用简单的Curl请求或浏览器困难。幸运的是,有一个伟大的WebSocket客户端工具,您可以用于测试您的服务器: //www.websocketking.com。值得注意的是,正如写入这一点,只支持与Localhost的连接只支持Chrome。

基本服务器

现在您的工具已准备就绪,是时候设置一个非常基本的WebSocket服务器了。将本章的入门项目复制到您喜欢的位置,并在该目录中打开终端窗口。

cd share-touch-server
open Package.swift

echo服务器

打开 websockets.swift. 并将以下内容添加到结尾 sockets(_:) to create an echo endpoint:

// 1
app.webSocket("echo") { req, ws in
  // 2
  print("ws connected")
  // 3
  ws.onText { ws, text in
    // 4
    print("ws received: \(text)")
    // 5
    ws.send("echo: " + text)
  }
}
Connected to ws://localhost:8080/echo
Connecting to ws://localhost:8080/echo

会话

既然您已验证您可以与服务器通信,是时候为其添加更多功能了。对于基本应用程序,您将使用单个WebSocket端点 /会议.

客户 -> Server

从客户端到服务器的连接可以是三个州之一:加入,移动和留下。

加入

新的参与者将使用使用的WebSocket /会议 端点。在开放请求中,您将包括来自用户的两位信息:使用的颜色 - 表示为使用相对点表示的R,G,B,A和起始点。

搬了

为了使事情简单,在客户端打开一个新会话之后,它将发送服务器的唯一方法是用户拖动圆圈的新相对点。

剩下

此服务器将解释客户端的任何关闭,即离开房间。这使事情简洁。

服务器 -> Client

服务器向客户端发送三种不同类型的消息:加入,移动和左。

加入

当服务器发送一个 加入 消息,它包括在消息中,一个参与者的一个id,颜色和最后一个已知点。

搬了

任何时候参与者移动,服务器都会通知客户端。这些通知仅包括ID和新的相对点。

剩下

任何时候参与者从会话断开连接,服务器会通知所有其他参与者并删除该用户从关联的视图中。

设置“加入”

打开 websockets.swift. 并将以下内容添加到结尾 sockets(_:)

// 1
app.webSocket("session") { req, ws in
  // 2
  ws.onText { ws, text in
    print("got message: \(text)")
  }
}

iOS.project

本章的材料包括完整的iOS应用程序。您可以更改您要使用的URL sharetouchapp.swift.swift.. For now, it should be set to ws://localhost:8080/session. Build and run the app in the simulator. Select a color and press 开始,然后在屏幕周围拖动圆圈。您应该在服务器应用程序中看到日志,这些应用程序看起来类似于以下内容:

got message: {"x":0.62031250000000004,"y":0.60037878787878785}
got message: {"x":0.61250000000000004,"y":0.59469696969696972}
got message: {"x":0.60781249999999998,"y":0.59185606060606055}
got message: {"x":0.59999999999999998,"y":0.59469696969696972}

完成“加入”

如前所述,客户端将包括Web套接字连接请求中的颜色和起始位置。 WebSocket请求被视为升级的GET请求,因此您将在请求的查询中包含数据。在 websockets.swift., replace the code you added earlier for app.webSocket("session") with the following:

app.webSocket("session") { req, ws in
  // 1
  let color: ColorComponents
  let position: RelativePoint

  do {
    color = try req.query.decode(ColorComponents.self)
    position = try req.query.decode(RelativePoint.self)
  } catch {
    // 2
    _ = ws.close(code: .unacceptableData)
    return
  }
  // 3
  print("new user joined with: \(color) at \(position)")
}
print("new user joined with: \(color) at \(position)")
let newId = UUID().uuidString
TouchSessionManager.default
  .insert(id: newId, color: color, at: position, on: ws)

处理“移动”

接下来,您需要收听客户端的邮件。目前,您只需希望收到一条 相对点 objects. In this case, you’ll use onText(_:). Using onText(_:) is perhaps slightly less performant than using onBinary(_:) and receiving data directly. However, it makes debugging easier and you can change it later.

// 1
ws.onText { ws, text in
  do {
    // 2
    let pt = try JSONDecoder()
      .decode(RelativePoint.self, from: Data(text.utf8))
    // 3
    TouchSessionManager.default.update(id: newId, to: pt)
  } catch {
    // 4
    ws.send("unsupported update: \(text)")
  }
}

实施“左”

Finally, you need to implement the code for a WebSocket close. You’ll consider any disconnect or cancellation that leaves the socket unable to send messages as a close. Below ws.onText(_:), add:

// 1
_ = ws.onClose.always { result in
  // 2
  TouchSessionManager.default.remove(id: newId)
}

实现TouchSessionManager:加入

此时,您可以在TouchSessionManager中成功将WebSocket事件发送到其关联的架构事件。接下来,您需要实现管理逻辑。打开 touchsessionManager.swift. and replace the body of insert(id:color:at:on:) with the following:

// 1
let start = SharedTouch(
  id: id,
  color: color,
  position: pt)
let msg = Message(
  participant: id,
  update: .joined(start))
// 2
send(msg)

// 3
participants.values.map {
  Message(
    participant: $0.touch.participant,
    update: .joined($0.touch))
} .forEach { ws.send($0) }

/// store new session
// 4
let session = ActiveSession(touch: start, ws: ws)
participants[id] = session

实现TouchSessionManager:移动

Next, to handle “moved” messages, replace the body of update(id:to:) with the following code:

// 1
participants[id]?.touch.position = pt
// 2
let msg = Message(participant: id, update: .moved(pt))
// 3
send(msg)

实现touchsessionManager:左

Finally, you need to handle closes and cancellations. Replace the body of remove(id:) with the following:

// 1
participants[id] = nil
// 2
let msg = Message(participant: id, update: .left)
// 3
send(msg)

然后去哪儿?

你已经完成了。您的iOS应用程序通过WebSockets使用Swift Server实时通信。许多不同类型的应用程序可以从WebSockets所做的瞬时通信中受益,包括诸如聊天应用程序,游戏,飞机跟踪器等事物等的东西。如果您想象的应用程序需要实时响应,WebSocket可能是您的答案!

挑战

有关WebSockets的更多练习,请尝试以下挑战:

有一个技术问题?想报告一个错误吗? 您可以向官方书籍论坛中的书籍作者提出问题和报告错误 这里.

有反馈分享在线阅读体验吗? 如果您有关于UI,UX,突出显示或我们在线阅读器的其他功能的反馈,您可以将其发送到设计团队,其中表格如下所示:

© 2021 Razeware LLC

您可以免费读取,本章的部分显示为 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

要突出或记笔记,您需要在订阅中拥有这本书或自行购买。