【问题标题】:Swift TCP: safe buffer size for `Darwin.send` functionSwift TCP:`Darwin.send` 函数的安全缓冲区大小
【发布时间】:2016-06-17 14:44:39
【问题描述】:

我正在 Swift 3 中为 macOS 和 iOS 构建一个小型且易于使用的 TCP 框架(有一天它会支持 Linux)。这是我探索的新事物,这就是为什么存在潜在的混乱和错误的原因。

我的内部代码如下所示:

if Darwin.send(self._fileDescriptor._value, data.withUnsafeBytes { $0 }, data.count, 0)._isMinusOne() {

    try Error._throw(type: .network)
}

发送小包不是问题,但是当我尝试发送大包时,我的应用程序崩溃了(我试图一次发送 1590784 个字节)。之后我调查了问题,发现我错过了可以传递给Darwin.send 函数的限制。我一直在网上搜索以找到一个好的答案,但不幸的是,我找到了一些关于这个特定主题的数字(65K、1500 等)。

我的问题是我应该在Darwin.send 函数中使用什么最大缓冲区大小才能始终保持安全?

我在该特定领域没有那么丰富的经验,所以如果我的问题的答案能解释为什么您认为您选择的尺寸是最好和最安全的选择,那就太好了。

【问题讨论】:

  • XY 问题。定义“崩溃”。提供症状。证据。问题。把猜测留在家里。
  • @EJP 这个问题很清楚! JeremyP 给了我很好的反馈来解决我的问题。我没有问为什么我的应用程序首先崩溃了!

标签: swift sockets tcp darwin swift3


【解决方案1】:

我不知道您可以传递给send() 的缓冲区大小有限制。

但是,将您作为参数获得的指针返回到data.withUnsafeBytes 中的块是不安全的。我认为您不能保证它在块返回后指向有效的内存区域。

你应该试试

let bytesSent = data.withUnsafeBytes{
    return Darwin.send(self._fileDescriptor._value, $0, data.count, 0)
}

更新

我已经检查了source code 中的withUnsafeBytes 并且我可以确认方法调用没有做出任何努力来保留指向超出您传递给它的闭包范围的内存。您要做的是在释放内存后引用内存。我确定这是导致您崩溃的原因。

【讨论】:

  • 就我现在可以说的限制是物理的而不是逻辑的。正如我在帖子中提到的,当我将一个非常大的缓冲区传递给函数时,我的应用程序崩溃了。我修改了我的代码以在闭包内发送(很好的捕获),但结果是一样的。现在我正在重建我的自定义发送算法,将数据拆分成更小的包,看看上面提到的问题是否会消失(我认为应该),但我的问题仍然是:对于Darwin.send,什么缓冲区大小是安全的!?
  • 好的,我现在可以确认这种通过将数据分割成更小的包的方法效果很好并且符合预期(至少在我的 MacBook 上)。
  • @DevAndArtist 传递给发送系统调用的缓冲区没有限制。发生的事情是它发送它可以发送的内容并返回发送的字节数(如果有错误,则返回 -1)。缓冲区的大小不是问题。
  • 所以这可能意味着我必须检查 send 的结果是否不等于我发送的数据并重新发送其余数据(每次迭代我都会检查 -1) .那是对的吗?我现在假设,如果我的数据大于套接字缓冲区大小,那么这样就无关紧要了。
  • @DevAndArtist 没错。我想我可以通过将我的片段放入一个循环中,然后用子数据替换数据(使用subData() 方法)直到我的数据大小为零(或发生错误)。
猜你喜欢
  • 2015-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 2010-10-11
  • 2019-12-18
相关资源
最近更新 更多