Задержка многопользовательского подключения - PullRequest
0 голосов
/ 28 октября 2018

Итак, я пытался использовать многопользовательскую связь для управления игрой AppleTV с помощью устройства iOS.В целях тестирования я перенес игру на MacOS для целей тестирования, учитывая тот факт, что симулятор appleTV сильно отстает при использовании spriteKit.

Я столкнулся с проблемой задержек между отправкой и получением данных, которые я считаю невозможными.играть с учетом того, что я посылаю данные датчика.Я попытался с помощью sendData () и попытался использовать Stream. Задержки отсутствуют, когда устройство подключено к компьютеру с помощью кабеля молнии.

Я играл во многие игры, в которых в качестве контроллеров используются устройства iOS, и я предположил, что они используют Multipeer Connectivity. Есть ли лучшая альтернатива для этой цели?

Возможно, это проблема кода, но я сильно сомневаюсь в этом. Любая помощь приветствуется.


Браузер

import Foundation
import MultipeerConnectivity

var defaults = UserDefaults()

class GameService : NSObject, MCSessionDelegate, StreamDelegate {

    static var shared = GameService() //shared global instance of this class

    var playerNumbers: [MCPeerID : UInt8] = [:]
    private let myPeerID: MCPeerID
    private let serviceName = "olik"
    private let serviceBrowser: MCNearbyServiceBrowser
    var dataDelegate:DataPassingDelegate?

    lazy var session : MCSession = {
        let session = MCSession(peer: self.myPeerID, securityIdentity: nil, encryptionPreference: .required)
        session.delegate = self
        return session
    }()

    override init() {
        self.myPeerID = MCPeerID(displayName: "AppleTV")
        self.serviceBrowser = MCNearbyServiceBrowser(peer: myPeerID, serviceType: serviceName)

        super.init()
        self.serviceBrowser.delegate = self
        startBrowsing()
    }

    func startBrowsing() {
        serviceBrowser.startBrowsingForPeers()
    }
    func stopBrowsing() {
        serviceBrowser.stopBrowsingForPeers()
    }

    func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
        if state == MCSessionState.connected {

            let newNumber = UInt8(playerNumbers.count)
            playerNumbers[peerID] = newNumber
            let data = Data(from: UInt8(exactly: newNumber))
            do {
                try self.session.send(data, toPeers: [peerID], with: .reliable)
                NSLog("%@", "sending player number \(newNumber) to peer with display Name: \(peerID.displayName)")
            }
            catch let error {
                NSLog("%@", "Error for sending: \(error)")
            }
        }
    }

    func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
    }

    func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
        NSLog("%@", "recieved stream")
        stream.delegate = self
        stream.schedule(in: RunLoop.main, forMode: RunLoop.Mode.default)
        stream.open()

    }

    func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
    }

    func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
    }


    func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
        print("stream event, stream: \(aStream)")

        if let inputStream = aStream as? InputStream, eventCode == Stream.Event.hasBytesAvailable {
            print("bytes available")

            var bytes = [UInt8](repeating:0, count: 2)
            inputStream.read(&bytes, maxLength: 2)

            dataDelegate?.passData(sender: bytes[0], data: bytes[1])

            /*
             var userInfo: [String: UInt8] = [:]
             userInfo["sender"] = bytes[0]

             userInfo["data"] = bytes[1]

             DispatchQueue.main.async {
             NotificationCenter.default.post(name: dataNotification, object: nil, userInfo: userInfo)
             */
        }
    }
}


extension GameService: MCNearbyServiceBrowserDelegate {
    func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
        NSLog("%@", "found peer with display name: \(peerID.displayName)")
        browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: 0)
    }

    func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
        NSLog("%@", "lost peer with display name: \(peerID.displayName)")
    }
}

protocol DataPassingDelegate {
    func passData(sender: UInt8, data: UInt8)
}

extension Data {

    init<T>(from value: T) {
        var value = value
        self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }

    func to<T>(type: T.Type) -> T {
        return self.withUnsafeBytes { $0.pointee }
    }
}

Рекламодатель (устройство iOS)

import Foundation
import MultipeerConnectivity

var defaults = UserDefaults()

let notificationConnecting = Notification.Name(rawValue: "com.notification.MPCconnecting")
let notificationConnected = Notification.Name(rawValue: "com.notification.MPCconnected")
let notificationSearching = Notification.Name(rawValue: "com.notification.MPCsearching")
let notificationDisconnected = Notification.Name(rawValue: "com.notification.MPCdisconnected")


class GameService: NSObject, StreamDelegate {

    static var shared = GameService() //shared global instance of this class

    private var connection: MCSessionState
    private let myPeerID: MCPeerID
    private let serviceName = "olik"
    private let serviceAdvertiser : MCNearbyServiceAdvertiser
    private var outputStream: OutputStream?
    var appleTvPeer: MCPeerID?
    private var playerNumber: Int8?

    lazy var session : MCSession = {
        let session = MCSession(peer: self.myPeerID, securityIdentity: nil, encryptionPreference: .required)
        session.delegate = self
        return session
    }()

    override init() {
        connection = MCSessionState.notConnected

        myPeerID = MCPeerID(displayName: defaults.string(forKey: "displayName") ?? UIDevice.current.name)
        //create peerID with displayName in defaults. If nil, use device name

        serviceAdvertiser = MCNearbyServiceAdvertiser(peer: myPeerID, discoveryInfo: nil, serviceType: serviceName)
        //create Advertiser

        super.init()
        serviceAdvertiser.delegate = self
    }

    func startAdvertising() {
        //start Advertising Peer
        appleTvPeer = nil
        self.serviceAdvertiser.startAdvertisingPeer()
        DispatchQueue.main.async {
            NotificationCenter.default.post(name: notificationSearching, object: nil, userInfo: nil)
        }
    }

    func stopAdvertising() {
        //stop Advertising Peer
        self.serviceAdvertiser.stopAdvertisingPeer()
    }

    func sendData(data: Int8) {


        let dataToSend: [UInt8] = [UInt8(bitPattern: playerNumber!), UInt8(bitPattern: data)]
        let bytesWritten = outputStream?.write(dataToSend, maxLength: 2)
        NSLog("%@", "writing bytes \(dataToSend) to outputStream")

        /*
        do {
            try self.session.send(dataToSend, toPeers: [appleTvPeer!], with: .unreliable)
            NSLog("%@", "sending data: \(data) to peer \(String(describing: appleTvPeer))")

        }
        catch let error {
            NSLog("%@", "Error for sending: \(error)")
        }
        */
    }

}

enum ConnectionState {
    case notConnected //The device is advertising but didnt find a connection
    case connecting //The device is in the Connecting process
    case connected //The device is succesfully connected - pressing the button while in this state should disconnect from Browser
}


extension GameService: MCNearbyServiceAdvertiserDelegate {
    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
        NSLog("%@", "recieved an invitation from peer with display name: \(peerID.displayName)")
        invitationHandler(true, self.session)
        appleTvPeer = peerID
    }
}

extension GameService: MCSessionDelegate {
    func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
        if peerID == appleTvPeer {
            switch state {
            case .notConnected:
                NSLog("%@", "lost connection from peer with display name: \(peerID.displayName)")
                DispatchQueue.main.async {
                    NotificationCenter.default.post(name: notificationDisconnected, object: nil, userInfo: nil)
                }
            case .connecting:
                NSLog("%@", "now connecting to peer with display name: \(peerID.displayName)")
                DispatchQueue.main.async {
                    NotificationCenter.default.post(name: notificationConnecting, object: nil, userInfo: nil)
                }
            case .connected:
                NSLog("%@", "succesfully connected to peer with display name: \(peerID.displayName)")
                DispatchQueue.main.async {
                    NotificationCenter.default.post(name: notificationConnected, object: nil, userInfo: nil)
                }


            }

        }
    }

    func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
        // get data from appleTV
        let int = data.to(type: Int8.self)
        NSLog("%@", "recieved data from peer: \(int)")
        if int < 10 {
            // if the number sent is between 0-9, set it as player number
            playerNumber = int
            NSLog("%@", "recieved player number: \(int)")

            do {
                try outputStream = session.startStream(withName: String(int), toPeer: peerID)
                NSLog("%@", "created output stream")
            } catch {
                print("error in creating OutputStraeam")
            }
            outputStream?.delegate = self
            //outputStream?.setValue(playerNumber, forKey: "playerNumber")
            outputStream?.schedule(in: RunLoop.main, forMode: RunLoop.Mode.default)
            outputStream?.open()
        }


    }

    func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {

    }

    func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {

    }

    func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {

    }


}

extension Data {

    init<T>(from value: T) {
        var value = value
        self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }

    func to<T>(type: T.Type) -> T {
        return self.withUnsafeBytes { $0.pointee }
    }
}
...