import Foundation import Network protocol SocketDelegate: AnyObject { func didChangeState(socket: String, state: SocketState) func didReceiveMessage(socket: String, message: String) } public class Socket: NSObject { var id: String var host: String var port: Int var useTLS: Bool var acceptInvalidCertificates: Bool var connection: NWConnection? weak var delegate: SocketDelegate? public init(id: String, host: String, port: Int, useTLS: Bool, acceptInvalidCertificates: Bool) { self.id = id self.host = host self.port = port self.useTLS = useTLS self.acceptInvalidCertificates = acceptInvalidCertificates } public func connect() { let connection = NWConnection(host: NWEndpoint.Host(self.host), port: NWEndpoint.Port(String(self.port))!, using: .tcp) connection.stateUpdateHandler = self.stateDidChange(to:) self.receive(on: connection) connection.start(queue: .main) self.connection = connection } public func write(_ message: String) { if let data = message.data(using: .utf8) { connection?.send(content: data, completion: .idempotent) } } public func disconnect() { connection?.forceCancel() } func stateDidChange(to state: NWConnection.State) { switch state { case .setup: print("connection setup") break case .waiting(let error): print("connection waiting: \(error)") break case .preparing: self.delegate?.didChangeState(socket: self.id, state: .connecting) break case .ready: self.delegate?.didChangeState(socket: self.id, state: .connected) break case .failed(let error): print("connection failed: \(error)") break case .cancelled: self.delegate?.didChangeState(socket: self.id, state: .disconnected) break default: print("other") break } } func receive(on connection: NWConnection) { connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, contentContext, isComplete, error) in if let data = data, !data.isEmpty { if let message = String(data: data, encoding: .utf8) { self.delegate?.didReceiveMessage(socket: self.id, message: message) } } self.receive(on: connection) } } }