多对等连接延迟

时间:2018-10-28 08:16:54

标签: swift multipeer-connectivity

因此,我一直在尝试使用多对等连接来通过iOS设备控制appleTV游戏。出于测试目的,考虑到appleTV模拟器在使用spriteKit时滞后的事实,我将游戏移植到MacOS进行测试。

我遇到了发送和接收数据之间的延迟问题,考虑到我正在发送传感器数据,我发现这是不可能的。我尝试使用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 }
    }
}

0 个答案:

没有答案