CFSocketSetAddress 绑定失败:重新打开流后为 48
CFSocketSetAddress bind failure: 48 after reopening stream
你好,在我的 iOS Swift 应用程序中,我正在显示实时流。
因此我创建了这个函数来启动流,它在加载特定 containerView 时调用:
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 函数中调用此方法并设置通知函数如下:
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()
}
clearstream 和 restartStream 函数如下所示:
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 绑定失败:48 错误,当我将视图切换到另一个视图然后切换回流所在的视图时 运行。
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;
}
我不明白为什么会出现此错误,而我正在执行相同的过程来启动流。谁能帮帮我?
我也在寻找解决方案。
为什么不使用下面的 CFSocketSetAddress
if (0 != (err = bind(sock, (struct sockaddr *)&addr, sizeof(addr)))) {
NSLog(@"Bind error");
return false;
}
因为在文档中,
This function binds the socket by calling bind, and if the socket supports it, configures the socket for listening by calling listen with a backlog of 256.
使用 bind 对我有用,现在我也在寻找使用 CFSocketSetAddress 的方法。
你好,在我的 iOS Swift 应用程序中,我正在显示实时流。
因此我创建了这个函数来启动流,它在加载特定 containerView 时调用:
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 函数中调用此方法并设置通知函数如下:
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()
}
clearstream 和 restartStream 函数如下所示:
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 绑定失败:48 错误,当我将视图切换到另一个视图然后切换回流所在的视图时 运行。
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;
}
我不明白为什么会出现此错误,而我正在执行相同的过程来启动流。谁能帮帮我?
我也在寻找解决方案。
为什么不使用下面的 CFSocketSetAddress
if (0 != (err = bind(sock, (struct sockaddr *)&addr, sizeof(addr)))) {
NSLog(@"Bind error");
return false;
}
因为在文档中,
This function binds the socket by calling bind, and if the socket supports it, configures the socket for listening by calling listen with a backlog of 256.
使用 bind 对我有用,现在我也在寻找使用 CFSocketSetAddress 的方法。