我的 websocket 服务器出现问题,无法从 websocket 客户端获取消息。据我了解,对于 ws 连接,客户端发送升级命令,服务器使用 Switching 协议状态代码和 Accept-Key 对其进行响应。我根据下面的代码实现了这个:
final class DummyHandler: ChannelInboundHandler {
typealias InboundIn = HTTPServerRequestPart
typealias OutboundOut = HTTPServerResponsePart
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
print("channelRead called ....")
let part = self.unwrapInboundIn(data)
switch part {
case .head(let header):
if(header.headers.contains(name: "Sec-WebSocket-Key"))
{
let acceptKey = calculateAcceptKey(inKey: header.headers["Sec-WebSocket-Key"][0])
var headers = HTTPHeaders()
headers.add(name: "Upgrade", value: "websocket")
headers.add(name: "Connection", value: "Upgrade")
headers.add(name: "Sec-WebSocket-Accept", value: acceptKey!)
let responseHead = HTTPResponseHead(version: .init(major: 1, minor: 1), status: .switchingProtocols, headers: headers)
print(responseHead)
context.write(self.wrapOutboundOut(.head(responseHead)), promise: nil)
context.flush()
}
// ignore incoming content to keep it micro :-)
case .body:
print("body")
break
case .end:
print("End")
break
}
}
func calculateAcceptKey(inKey: String) -> String?
{
if(inKey != nil)
{
let input = inKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
let result = input.sha1()
return result
}
return nil
}
}
和服务器根据:
class Server {
// MARK: - Initializers
init(host: String, port: Int) {
self.host = host
self.port = port
}
// MARK: - Public functions
func start() {
do {
print("server is starting .........")
let bootstrap = NIOTSListenerBootstrap(group: group)
.childChannelInitializer { channel in
channel.pipeline.configureHTTPServerPipeline()
.flatMap {
channel.pipeline.addHandler(DummyHandler())
}
}
let channel = try bootstrap
.bind(host: host, port: port)
.wait()
try channel.closeFuture.wait()
} catch {
print("An error happed \(error.localizedDescription)")
exit(0)
}
}
func myTLSOptions() -> NWProtocolTLS.Options {
let options = NWProtocolTLS.Options()
let yourSecIdentity = getIdentity(password: "xxxx")// you have to implement something here
sec_protocol_options_set_peer_authentication_required(options.securityProtocolOptions, false)
sec_identity_create(yourSecIdentity!)
return options
}
func getIdentity (password : String?) -> SecIdentity? {
// Load certificate file
let path = Bundle.main.url(forResource: "cert.p12", withExtension: nil, subdirectory: "/file")
print(path)
//let fileUrl = URL(string: path!)!
let data = try! Data.init(contentsOf: path!)
let options = [ kSecImportExportPassphrase as String: password ]
var rawItems: CFArray?
let status = SecPKCS12Import(data as CFData,
options as CFDictionary,
&rawItems)
guard status == errSecSuccess else {
print("Failed")
return nil
}
let items = rawItems! as! Array<Dictionary<String, Any>>
let firstItem = items[0]
let identity = firstItem[kSecImportItemIdentity as String] as! SecIdentity?
print(identity)
return identity
}
func stop() {
do {
try group.syncShutdownGracefully()
} catch {
print("An error happed \(error.localizedDescription)")
exit(0)
}
}
// MARK: - Private properties
private let group = NIOTSEventLoopGroup()
private var host: String
private var port: Int
}
我通过这个站点测试我的代码:http: //livepersoninc.github.io/ws-test-page/?
该站点正确打开了套接字,并且站点中的状态更改为已连接,但是在点击发送消息后,我的服务器中没有任何反应,并且我无法收到任何消息。如果有人指导我错过了什么,我将不胜感激。