Class PeerListener
import Network
@available(iOS 13.0, *)
var sharedListener: PeerListener?
@available(iOS 13.0, *)
class PeerListener {
weak var delegate: PeerConnectionDelegate?
var listener: NWListener?
var name: String
// Create a listener with a name to advertise, a passcode for authentication,
// and a delegate to handle inbound connections.
init(name: String, delegate: PeerConnectionDelegate) {
self.delegate = delegate
self.name = name
startListening()
}
// Start listening and advertising.
func startListening() {
do {
// Create the listener object.
let tcpOption = NWProtocolTCP.Options()
tcpOption.enableKeepalive = true
tcpOption.keepaliveIdle = 2
let params = NWParameters(tls: nil, tcp: tcpOption) /* Configure TLS here */
params.includePeerToPeer = true
let listener = try NWListener(using: params)
self.listener = listener
// Set the service to advertise.
listener.service = NWListener.Service(name: self.name, type: "_whitelion._udp")
listener.stateUpdateHandler = { newState in
switch newState {
case .ready:
print("Listener ready on \(String(describing: listener.port))")
case .failed(let error):
// If the listener fails, re-start.
if error == NWError.dns(DNSServiceErrorType(kDNSServiceErr_DefunctConnection)) {
print("Listener failed with \(error), restarting")
listener.cancel()
self.startListening()
} else {
print("Listener failed with \(error), stopping")
self.delegate?.displayAdvertiseError(error)
listener.cancel()
}
case .cancelled:
sharedListener = nil
default:
break
}
}
listener.newConnectionHandler = { newConnection in
if let delegate = self.delegate {
if sharedConnection == nil {
// Accept a new connection.
sharedConnection = PeerConnection(connection: newConnection, delegate: delegate)
} else {
// If a game is already in progress, reject it.
newConnection.cancel()
}
}
}
// Start listening, and request updates on the main queue.
listener.start(queue: .main)
} catch {
print("Failed to create listener")
abort()
}
}
// If the user changes their name, update the advertised name.
func resetName(_ name: String) {
self.name = name
if let listener = listener {
// Reset the service to advertise.
listener.service = NWListener.Service(name: self.name, type: "_tictactoe._tcp")
}
}
}
Class PeerConnection
import Foundation
import Network
@available(iOS 13.0, *)
var sharedConnection: PeerConnection?
@available(iOS 13.0, *)
protocol PeerConnectionDelegate: AnyObject {
func connectionReady()
func connectionFailed()
func receivedMessage(content: Data?, message: NWProtocolFramer.Message)
func displayAdvertiseError(_ error: NWError)
}
@available(iOS 13.0, *)
class PeerConnection {
weak var delegate: PeerConnectionDelegate?
var connection: NWConnection?
let initiatedConnection: Bool
// Create an outbound connection when the user initiates a game.
init(endpoint: NWEndpoint, interface: NWInterface?, delegate: PeerConnectionDelegate) {
self.delegate = delegate
self.initiatedConnection = true
let connection = NWConnection(host: "255.255.255.255", port: 13001, using: .udp)
self.connection = connection
startConnection()
}
// Handle an inbound connection when the user receives a game request.
init(connection: NWConnection, delegate: PeerConnectionDelegate) {
self.delegate = delegate
self.connection = connection
self.initiatedConnection = false
startConnection()
}
// Handle the user exiting the game.
func cancel() {
if let connection = self.connection {
connection.cancel()
self.connection = nil
}
}
// Handle starting the peer-to-peer connection for both inbound and outbound connections.
func startConnection() {
guard let connection = connection else {
return
}
connection.stateUpdateHandler = { newState in
switch newState {
case .ready:
print("\(connection) established")
// When the connection is ready, start receiving messages.
self.receiveNextMessage()
// Notify your delegate that the connection is ready.
if let delegate = self.delegate {
delegate.connectionReady()
}
case .failed(let error):
print("\(connection) failed with \(error)")
// Cancel the connection upon a failure.
connection.cancel()
// Notify your delegate that the connection failed.
if let delegate = self.delegate {
delegate.connectionFailed()
}
default:
break
}
}
// Start the connection establishment.
connection.start(queue: .main)
}
// Handle sending a "move" message.
func sendMove(_ move: String) {
guard let connection = connection else {
return
}
// Create a message object to hold the command type.
let message = NWProtocolFramer.Message(gameMessageType: .move)
let context = NWConnection.ContentContext(identifier: "Move",
metadata: [message])
// Send the application content along with the message.
connection.send(content: move.data(using: .unicode), contentContext: context, isComplete: true, completion: .idempotent)
}
// Receive a message, deliver it to your delegate, and continue receiving more messages.
func receiveNextMessage() {
guard let connection = connection else {
return
}
connection.receiveMessage { (content, context, isComplete, error) in
// Extract your message type from the received context.
if let gameMessage = context?.protocolMetadata(definition: GameProtocol.definition) as? NWProtocolFramer.Message {
self.delegate?.receivedMessage(content: content, message: gameMessage)
}
if error == nil {
// Continue to receive more messages until you receive and error.
self.receiveNextMessage()
}
}
}
}
But although I got error like "No Route to Host"