如何使用 NSStream 连接到主机名具有附加路径的 wss 套接字?

How to connect to wss socket where host name has additional path using NSStream?

我正在尝试连接到 wss 套接字,主机名如下所示:"myhostname.com/ws/v2"。 以下是我如何开始连接:

let host = "myhostname.com/ws/v2"

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host as CFString, 443, &readStream, &writeStream)

inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()

outputStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey)
inputStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey)

inputStream.schedule(in: .current, forMode: .commonModes)
outputStream.schedule(in: .current, forMode: .commonModes)

inputStream.delegate = self
outputStream.delegate = self

inputStream.open()
outputStream.open()

失败并出现错误: The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 1.)

但是,如果我从主机名中删除路径,它看起来像这样:myhostname.com 然后在我的委托中我得到一个事件 openCompleted。但是,此后它没有响应我的消息,我认为这是因为我连接到错误的套接字,因为我删除了路径。

当主机名有附加路径时,连接到套接字的正确方法是什么?

myhostname.com/ws/v2 不是主机名。它是一个(不完整的)URL(完整的 URL 是 wss://myhostname.com/ws/v2)。主机名只是 myhostname.com,该主机上的 Websocket 路径只是 /ws/v2.

WebSockets 握手使用 HTTP/S,因此仅使用 NSStream 连接到主机是不够的。您必须将 TCP 套接字连接到 host 和端口,然后如果使用 WSS 协商 SSL/TLS 握手,然后使用 HTTP 请求 path 请求 Upgrade WebSocket,并且仅当返回成功的 HTTP 101 回复时才执行 WebSocket 握手。

需要手动完成大量工作。您真的应该改用实际的 WebSocket 客户端库。有很多可用的。