【问题标题】:Swift: TCP socket keep-aliveSwift:TCP 套接字保持活动状态
【发布时间】:2014-09-02 20:58:04
【问题描述】:

我正在开发一个 iOS 应用程序(使用 Swift),它使用 TCP 连接到 TCP 服务器。目前,只要我发送了一些东西,连接就会自动关闭。我想保持连接打开/活动,直到我手动关闭它。

this Objective-C-based question我发现在Objective-C中可以这样实现:

#include <sys/socket.h>
...
CFDataRef socketData = CFReadStreamCopyProperty((__bridge CFReadStreamRef)(stream), kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle socket;
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket);
CFRelease(socketData);

int on = 1;
if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) {
    NSLog(@"setsockopt failed: %s", strerror(errno));
}

我当前的 Swift 实现/翻译如下所示:

var socketData = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySocketNativeHandle) as CFDataRef
var socket: CFSocketNativeHandle
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8).self&socket)

var on: UInt8 = 1;
if setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, 255) == -1 {
}

一些注意事项:

  • inputStream 声明为:var inputStream: NSInputStream?
  • 我不确定使用255 替代sizeof(on) 是否是个好主意。
  • 代码发生在函数func stream(theStream:NSStream, handleEvent streamEvent:NSStreamEvent) 中,这是使用NSStreamDelegate 协议所必需的。
  • 我不确定使用inputStream 代替theStream(函数参数)是否是个好主意。

我在 CFDataGetBytes 函数上遇到 Xcode 错误。上面写着:

'NSData' 不是 'CFData' 的子类型

知道如何解决这个问题吗?

另外,如何在我的 Swift 文件中导入/包含 &lt;sys/socket.h&gt;?我见过一种叫做桥接头的东西,但这不只适用于 Obj-C 与 Swift 实现的并行吗?

【问题讨论】:

  • TCP keep-alive 是为了检测空闲连接上的错误。它对“自动关闭”没有帮助。后者是一个应用程序问题,需要查看您的代码才能提供帮助。

标签: ios sockets tcp swift


【解决方案1】:

CFDataRef 是“免费桥接”到NSData,因此第一部分可以是 更简单的写成

var socketData = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySocketNativeHandle) as NSData
var socket: CFSocketNativeHandle = 0
socketData.getBytes(&socket, length: sizeofValue(socket))

setsockopt() 的 "option_value" 参数是 int 的地址(映射到 Swift 为 UInt32),最后一个参数必须是该变量的大小:

var on: UInt32 = 1;
if setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, socklen_t(sizeofValue(on))) == -1 {
    let errmsg = String.fromCString(strerror(errno))
    println("setsockopt failed: \(errno) \(errmsg)")
}

默认导入&lt;sys/socket.h&gt;

【讨论】:

  • 感谢您的回答。如果我收到setsockopt failed: 0x00007ff369887200,你知道去哪里找吗?也就是说,setsockopt 函数返回 -1。
  • @eightx2:我已更新代码以在失败情况下显示正确的错误编号和消息。 - 可能的错误在手册页中列出(终端中的“man setsockopt”或developer.apple.com/library/ios/documentation/System/Conceptual/…)。
  • @eightx2:你有进步吗?
  • 感谢您的更新。我收到此错误:setsockopt failed: 22 Invalid argument。我了解到我必须只写 8 而不是 socklen_t(sizeofValue(on))
  • @eightx2:这意味着UInt8 不是套接字选项的正确数据类型。 C int 映射到Int32,因此您可能必须使用var on: UInt32 = 1(连同socklen_t(sizeofValue(on)))。
猜你喜欢
  • 2010-09-23
  • 2011-07-03
  • 1970-01-01
  • 2018-11-08
  • 2014-02-08
  • 1970-01-01
  • 2012-07-08
  • 2018-04-13
  • 1970-01-01
相关资源
最近更新 更多