2016-07-08 3 views
0

こんにちは私のiOS Swiftアプリケーションでは、ライブストリームを表示しています。CFSocketSetAddressバインドエラー:ストリームを再オープンした後に482

func startStream() { 

    let masterViewController = self.parentViewController as? MasterViewController 

    let ip = RTPTools().findLocalWifiIp() 
    print("local IP: \(ip)") 

    let view = masterViewController!.streamView 
    view.waiting = true 

    masterViewController!.receiver = RTPReceiver(localIp: ip, listenPort: 5000) 
    masterViewController!.receiver!.delegate = view 
    view.setNeedsDisplay() 

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MasterViewController.decodingFailed(_:)), name: AVSampleBufferDisplayLayerFailedToDecodeNotification, object: self.view.layer) 

    Connector.sharedInstance.runLivePreview() 

    masterViewController?.showStreamView() 
} 

私はviewDidAppear関数でこのメソッドを呼び出すと、このよう通知機能を設定しています:

そこで私は、特定のcontainerViewがロードされたときに呼び出されたストリームを、開始するには、この関数を作成しました:クリアストリームとrestartStream機能は次のように見ている

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 

    NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(InformationsViewController.restartStream), name: UIApplicationWillEnterForegroundNotification, object: nil) 
    NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(InformationsViewController.clearStream), name: UIApplicationWillResignActiveNotification, object: nil) 

    startStream() 
} 

func clearStream() { 
    let masterViewController = self.parentViewController as? MasterViewController 
    masterViewController!.receiver = nil 

    Connector.sharedInstance.stopLivePreview() 
} 

func restartStream() { 
    let masterViewController = self.parentViewController as? MasterViewController 

    let ip = RTPTools().findLocalWifiIp() 
    print("local IP: \(ip)") 

    let view = masterViewController!.streamView 
    view.waiting = true 

    masterViewController!.receiver = RTPReceiver(localIp: ip, listenPort: 5000) 
    masterViewController!.receiver!.delegate = view 
    view.setNeedsDisplay() 

    let videoLayer = view.layer as! AVSampleBufferDisplayLayer 
    videoLayer.flushAndRemoveImage() 

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MasterViewController.decodingFailed(_:)), name: AVSampleBufferDisplayLayerFailedToDecodeNotification, object: self.view.layer) 

    Connector.sharedInstance.runLivePreview() 

    masterViewController?.showStreamView() 
} 

ストリームが実行されているときにホームボタンをクリックしてから、アプリケーションに戻ると、すべてが正常に動作します。しかし、私はCFSocketSetAddressバインドエラーが発生します。ビューを別のビューに切り替えてから、ストリームが実行されているビューに戻ると、エラーが発生します。 RTPReceiverはこのように実装されて

@implementation RTPReceiver 

- (id) initWithLocalIp:(NSString*)ip listenPort:(uint16_t)port { 
    self = [super init]; 
    if (!self) { 
     return nil; 
    } 
    self.localIp = ip; 
    self.listenPort = port; 

    //create socket 
    CFSocketContext socketContext = {0, (__bridge void*)self, NULL, NULL, NULL}; 
    CFSocketRef socket = CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 
           kCFSocketDataCallBack , MySocketCallback, &socketContext); 
    NSAssert(socket, @"Socket creation failed"); 
    self.socket = socket; 
    CFRelease(socket); 

    //set address 
    struct sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_len = sizeof(addr); 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = inet_addr([self.localIp cStringUsingEncoding:NSASCIIStringEncoding]); 
    addr.sin_port = htons(self.listenPort); 
    NSData* address = [NSData dataWithBytes:&addr length: sizeof(addr)]; 

    // HERE IS THE ERROR 
    CFSocketError sockErr = CFSocketSetAddress(self.socket, (CFDataRef) address); 
    NSAssert(sockErr == kCFSocketSuccess,@"Set socket address failed"); 

    //add to run loop 
    CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.socket, 0); 
    CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopCommonModes); 
    CFRelease(source); 
    return self; 
} 

私はこのエラーを取得し、なぜ私は、ストリームを開始するために同じプロセスをやっている間、私は、理解していません。誰か助けてくれますか?

答えて

0

解決策も見つけています。

は、なぜあなたは

この関数は、バインドを呼び出してソケットをバインドし、そしてソケットがサポートしている場合、ソケットを設定し、そのための文書に代わりCFSocketSetAddress

if (0 != (err = bind(sock, (struct sockaddr *)&addr, sizeof(addr)))) { 
     NSLog(@"Bind error"); 
     return false; 
    } 

の下には使用しないでくださいバックログが256であることを聞いて聴くために。

使用するバインドは私のために働いて、今私はCFSocketSetAddressを使う方法を見いだしています。