Swift Multipeer Connectivity - 接收空数据的InputStream

时间:2017-10-25 08:50:42

标签: ios swift skscene multipeer-connectivity

我正在做一个基于MPC框架的多人游戏,用于玩家设备之间的数据通信(以及游戏的spritekit)。

逻辑是其中一个设备是主设备,执行所有游戏逻辑和计算,并将各种精灵的位置发送到只需更新精灵位置的从设备。

主人打开他和所有奴隶之间的流,并通过这些流发送各种数据。数据存储在类型(String,Any)的字典中。

问题有两个:

  • 一点一点地看到主设备发送数据的时间与从设备接收数据的时间之间存在差异
  • 主设备越多,发送的数据越多,从设备接收空/部分数据越多

我已经进行了各种检查和控制,我没有发送或接收函数抛出的错误,只丢失数据或空/部分数据。

以下是代码的一些相关部分。如果需要更多,请告诉我

THX

学家

主设备和从设备之间的流初始化

由主人执行

func InitMPCStream()
{
    for Peer in Session.connectedPeers
    {
        if Peer.displayName != gMasterPeerName
        {
            let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )

            try! gtListPlayerMulti[IndexPeer!].Stream = Session.startStream(withName: "Stream " + Peer.displayName, toPeer: Peer)

            gtListPlayerMulti[IndexPeer!].Stream!.delegate = self
            gtListPlayerMulti[IndexPeer!].Stream!.schedule(in: RunLoop.main, forMode:RunLoopMode.defaultRunLoopMode)
            gtListPlayerMulti[IndexPeer!].Stream!.open()
        }
    }
}

奴隶执行

func session(_ session: MCSession, didReceive InStream: InputStream, withName StreamName: String, fromPeer PeerID: MCPeerID)
{
    InputStream = InStream
    InputStream.delegate = self
    InputStream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
    InputStream.open()
}

将数据发送到从属设备的功能

此功能在SKScene的更新循环中在主端执行,每次更新几次,所以很频繁。

逻辑是,对于每个更新周期,会发生几个事件(10到100之间)。每个事件都会生成对此函数的调用。发送的数据量不是很重要:3到10行的(String,Any)字典,其中Any可以是字符串,数字(Int,CGFloat ...)或bool。

func SendStreamData(IDPeer: Int = 0, DataToSend: Dictionary<String, Any>)
{
    let DataConverted = NSKeyedArchiver.archivedData(withRootObject: DataToSend)

    if IDPeer == 0
    {
        for Peer in Session.connectedPeers
        {
            let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )
            if gtListPlayerMulti[IndexPeer!].Stream!.hasSpaceAvailable
            {
                let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
                if bytesWritten == -1 { print("Erreur send stream") } else { gSendingNumber = gSendingNumber + 1 }
            } else { print("No space in stream") }
        }
    }
    else
    {
        let IndexPeer = gtListPlayerMulti.index(where: { $0.ID == IDPeer } )

        let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
    }
}

从属端收到数据时调用的函数

func stream(_ aStream: Stream, handle eventCode: Stream.Event)
{
    switch(eventCode)
    {
    case Stream.Event.hasBytesAvailable:
        gSendingNumber = gSendingNumber + 1
        let InputStream = aStream as! InputStream
        var Buffer = [UInt8](repeating: 0, count: 1024)
        let NumberBytes = InputStream.read(&Buffer, maxLength:1024)
        let DataString = NSData(bytes: &Buffer, length: NumberBytes)
        if let Message = NSKeyedUnarchiver.unarchiveObject(with: DataString as Data) as? [String:Any] //deserializing the NSData
        { ProcessMPCDataReceived(VCMain: self, PeerID: PeerID, RawData: DataString as Data) }
        else { print("Empty Data") }

    case Stream.Event.hasSpaceAvailable:
        break

    case Stream.Event.errorOccurred:
        print("ErrorOccurred: \(aStream.streamError?.localizedDescription)")

    default:
        break
    }
}

这里的问题是NSKeyedUnarchiver.unarchiveObject行返回nil,因为DataString不符合预期的字典

0 个答案:

没有答案