iOS Multi Peer Connectivity outputStream.hasSpaceAvailable始终为false

时间:2018-01-07 12:27:35

标签: ios swift multipeer-connectivity

我正在尝试使用MPC开发多用户AR游戏。连接,发送和接收数据工作正常。但是,为了发送实时播放器位置信息,我想使用流来避免延迟问题。我可以启动流(我认为),但是当我尝试将数据写入输出流时,它只能工作一次。之后,outputstream.hasSpaceAvailable始终为false。我查看了整个网络,但找不到一个单独的示例,其中swift 3或4中使用了流。在我的项目的精简代码下面。希望有人能告诉我我做错了什么。

import UIKit
import SceneKit
import ARKit
import MultipeerConnectivity

class ViewController: UIViewController, ARSCNViewDelegate, MCNearbyServiceAdvertiserDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, StreamDelegate {

@IBOutlet var sceneView: ARSCNView!

let MultiPeerType = "artoytrain"
let myPeerId = MCPeerID(displayName: UIDevice.current.name)

var streamTargetPeer: MCPeerID?
var serviceAdvertiser : MCNearbyServiceAdvertiser!
var serviceBrowser : MCNearbyServiceBrowser!

var outputStream: OutputStream?

var counter = 0
var streaming = false

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

override func viewDidLoad() {
    super.viewDidLoad()

    sceneView.delegate = self

    startMPC()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARWorldTrackingConfiguration()

    // Run the view's session
    sceneView.session.run(configuration)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // Pause the view's session
    sceneView.session.pause()
}

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    if streaming {
        var float1 = Float(counter)
        let data = Data(buffer: UnsafeBufferPointer(start: &float1, count: 1))
        counter += 1

        guard let outputStream = outputStream else
        {
            print("no stream")
            return
        }
        if outputStream.hasSpaceAvailable == true
        {
            outputStream.write(data.withUnsafeBytes { $0.pointee }, maxLength: 4)
        }
        else
        {
            print("no space available")
        }
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

func session(_ session: ARSession, didFailWithError error: Error) {
    // Present an error message to the user

}

func sessionWasInterrupted(_ session: ARSession) {
    // Inform the user that the session has been interrupted, for example, by presenting an overlay

}

func sessionInterruptionEnded(_ session: ARSession) {
    // Reset tracking and/or remove existing anchors if consistent tracking is required

}

// Multi Peer Connectivity

//init
func startMPC() {
    serviceAdvertiser = MCNearbyServiceAdvertiser(peer: myPeerId, discoveryInfo: nil, serviceType: MultiPeerType)
    serviceBrowser = MCNearbyServiceBrowser(peer: myPeerId, serviceType: MultiPeerType)

    serviceAdvertiser.delegate = self
    serviceAdvertiser.startAdvertisingPeer()

    serviceBrowser.delegate = self
    serviceBrowser.startBrowsingForPeers()
}

// advertiser
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {
    print("didNotStartAdvertisingPeer: \(error)")
}

func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
    print("didReceiveInvitationFromPeer \(peerID)")
    invitationHandler(true, self.session)
}

// browser
func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
    print("didNotStartBrowsingForPeers: \(error)")
}

func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
    print("foundPeer: \(peerID)")

    streamTargetPeer = peerID

    browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: 10)
}

func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
    print("lostPeer: \(peerID)")
}

// session
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
    print("peer \(peerID) didChangeState: \(state)")

    connectedDevicesChanged(connectedDevices: session.connectedPeers.map{$0.displayName})
}

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

func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
    print("didReceiveStream",stream,streamName,stream.hasBytesAvailable)

    stream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
    stream.delegate = self
    stream.open()
}

func stream(_ stream: Stream, handle eventCode: Stream.Event)
{
    print("stream entered")
    if let inputStream = stream as? InputStream , eventCode == Stream.Event.hasBytesAvailable
    {
        var bytes = [UInt8](repeating: 0, count:4)
        inputStream.read(&bytes, maxLength: 4)

        print("input stream",bytes)
    }
}

func startStream()
{
    print("startstream")
    guard let streamTargetPeer = streamTargetPeer, outputStream == nil else
    {
        return
    }

    do
    {
        outputStream =  try session.startStream(withName: "stream", toPeer: streamTargetPeer)

        outputStream?.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)

        outputStream?.open()

        print("output stream is open")

        streaming = true
    }
    catch
    {
        print("unable to start stream!! \(error)")
    }
}

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

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

func connectedDevicesChanged(connectedDevices: [String]) {
    print("MM Connections: \(connectedDevices)")
    if connectedDevices.count > 0 {
        print("connected, so start streaming")
        startStream()
    }
}
}

0 个答案:

没有答案