我有以下用Objective-C编写的代码,用于将数据写入套接字。服务器在Ubuntu上运行node.js:
NSString *url = @"anIPAddress";
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)url, 9000, &readStream, &writeStream);
self.inputStream = (NSInputStream *)readStream;
self.outputStream = (NSOutputStream *)writeStream;
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
我能够连接到服务器并发送信息。但是我注意到几分钟后连接超时(我想5分钟左右?)。我怎样才能保持这种联系?我知道有一个断开连接,因为如果我连接到终端下的服务器,同样的事情发生,我必须保持该连接存活。我想我的代码中也发生了同样的事情。谢谢你的帮助!
答案 0 :(得分:6)
最简单的答案是尝试使用SO_KEEPALIVE
套接字选项。
如果没有端点之间的数据流动,很难检测到断开的连接,这使得此选项在某些方面无用,因为它不使用数据来检测断开的连接。但是,很容易添加到您的代码中查看。添加它,看它是否有帮助...
这是在C或C ++中完成的方式
int opt = 1;
// Get the native socket handle from your socket class here...
int socket_handle = getNativeSocketHandle( self.outputStream );
/*Enabling keep alive*/
if( setsockopt( socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof( opt ) ) < 0 )
{
// failed setting socket option
}
不那么简单的答案是在协议中添加ping
数据包并定期发送ping数据包,以便检测连接断开。
答案 1 :(得分:3)
您需要定期在连接上发送一些垃圾。试试这个:
NSTimer* t = [NSTimer scheduledTimerWithTimeInterval:240 target:self selector:@selector(timerMethod:) userInfo:[NSNumber numberWithInt:sockfd] repeats:YES];
然后在self
:
-(void)timerMethod:(NSTimer*)t
{
send([[t userInfo] intValue], "Keepalive!", 11, 0);
}
注意:替换“Keepalive!”随心所欲的协议。唯一的要求是远程端(套接字服务器)忽略该消息。
答案 2 :(得分:3)
我发现了如何做到这一点。由于服务器正在运行node.js,我使用了
socket.setKeepAlive(true, 2000);
以这种方式节点保持每个套接字打开。默认值为false,因此这就是超时的原因。我希望这对其他人有用。感谢您的回复,我认为保持心跳(保持活力)也是一个好主意,但是使用这种原生方法节点可以解决它。
答案 3 :(得分:3)
假设有一个NSOutputStream * oStream;
在iOS上这样做:
#if 1 // Using CF
CFDataRef data = (CFDataRef)CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)oStream, kCFStreamPropertySocketNativeHandle);
if(data) {
CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)CFDataGetBytePtr(data);
CFRelease(data);
#else // Using Foundation
NSData *data = (NSData *)[oStream propertyForKey:(__bridge NSString *)kCFStreamPropertySocketNativeHandle];
if(data) {
CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)[data bytes];
#endif
NSLog(@"SOCK HANDLE: %x", socket_handle);
/*Enabling keep alive*/
if( setsockopt( socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof( opt ) ) < 0 )
{
NSLog(@"Yikes 2: failed to set keepalive! ERRNO: %s", strerror(errno));
}
我发布这篇文章是因为我花了好几个小时全力以赴,想要为别人付出努力。