(in objective-c, not swift), I have tried prepending the websocket options with nw_protocol_stack_prepend_application_protocol to my existing tls/tcp parameters but it is failing to upgrade the connection status and throwing an error. I cannot find any good examples or documentation on the Apple developer forums for this. Why do none of the functions have examples?
I’m working with WebSockets today and I wanted a Swift version of the above. I ended up porting it line-for-line, so I thought I’d share it here for the benefit of others (and, most importantly, Future Quinn™ :-).
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
import Foundation
import Network
func main() {
print("will start")
let endpoint = NWEndpoint.url(URL(string: "ws://127.0.0.1:12345/test")!)
let params = NWParameters.tcp
let stack = params.defaultProtocolStack
let ws = NWProtocolWebSocket.Options(.version13)
stack.applicationProtocols.insert(ws, at: 0)
let connection = NWConnection(to: endpoint, using: params)
connection.stateUpdateHandler = { newState in
print("state did change, new: \(newState)")
}
connection.start(queue: .main)
let timer = DispatchSource.makeTimerSource(queue: .main)
timer.schedule(deadline: .now() + 1.0, repeating: 1.0)
timer.setEventHandler {
print("will send")
let message = Data("Hello Cruel World \(Date())".utf8)
let metadata = NWProtocolWebSocket.Metadata(opcode: .text)
let context = NWConnection.ContentContext(identifier: "send", metadata: [metadata])
connection.send(content: message, contentContext: context, isComplete: true, completion: NWConnection.SendCompletion.contentProcessed({ error in
print("did send, error: \(error.flatMap { "\($0)" } ?? "-")")
}))
}
timer.activate()
withExtendedLifetime(connection) {
dispatchMain()
}
}
main()
exit(EXIT_SUCCESS)
import Foundation
import Network
private func startReceive(connection: NWConnection) {
connection.receiveMessage { content, _, _, error in
if let error = error {
print("connection receive did fail, error: \(error)")
return
}
if let content = content {
print("connection did receive content, count: \(content.count)")
}
startReceive(connection: connection)
}
}
func main() throws {
print("will start")
var connections: [NWConnection] = []
let params = NWParameters.tcp
let stack = params.defaultProtocolStack
let ws = NWProtocolWebSocket.Options(.version13)
stack.applicationProtocols.insert(ws, at: 0)
let listener = try NWListener(using: params, on: 12345)
listener.stateUpdateHandler = { newState in
print("listener state did change, new: \(newState)")
}
listener.newConnectionHandler = { connection in
print("listener did accept connection")
connections.append(connection)
connection.stateUpdateHandler = { newState in
print("connection state did change, new: \(newState)")
}
connection.start(queue: .main)
startReceive(connection: connection)
}
listener.start(queue: .main)
withExtendedLifetime(listener) {
dispatchMain()
}
}
try! main()