不能在非阻塞模式下使用ASIO SSL套接字吗?

问题描述 投票:0回答:1

在 ASIO 中,非 SSL 套接字的类型为:

asio::ip::tcp::socket;

这是以下类型的定义:

asio::basic_stream_socket<asio::ip::tcp>

SSL 套接字是普通套接字的包装:

asio::ssl::stream<asio::ip::tcp::socket>;

我正在尝试将视频发送到 2MB 大的浏览器。我尝试使用 socket_type.write_some() 写入整个 2MB 数据 --- socket_type 是上面提到的两者之一。当我使用非 SSL socket_type 时,返回的字节数就是全部,全部 200 万。我设置了典型的循环,如果未写入全部字节数,我会写入其余部分(因为应该这样做)。并且浏览器端接收成功,都是2MB。

现在使用 SSL 套接字我尝试写入 2MB,我总是得到一些写入为 16,384 字节的字节,我了解到这是最大的 SSL 记录大小。好的,所以没有全部写完,没关系,我将在下一次调用中简单地写下剩余部分,然后再下一个,直到全部完成。尽管返回的错误代码是 WOULD_BLOCK,但我总是写入 16,384 个字节。

如果我将套接字设置为阻塞模式,它就可以正常工作。如果我在每次写入调用之间设置 100 毫秒的线程睡眠时间,它就可以正常工作。

唯一有效的结论:

套接字返回“WOULD_BLOCK”后尚未准备好写入更多数据。

但是如果它返回“WOULD_BLOCK”,为什么写入的字节数总是16,384?如果我尝试过早向其写入更多字节,为什么再次写入会产生错误(似乎在远程端和本地端)?它应该工作的方式(我认为)是,如果它会阻塞(由于写入太多,比如说缓冲区的完整数据和挂起的数据正在等待传输),那么写入的字节数可能会更少,或者为零总是 16,384。

非阻塞模式似乎不能与 ASIO 中的 SSL 套接字一起使用,因为当您收到消息 WOULD_BLOCK 时,无法知道何时可以再次写入。

c++ sockets asio
1个回答
0
投票

SSL 套接字基本上是无缓冲 I/O 上的缓冲层。这意味着它的行为并不完全像普通的 TCP 套接字。

如果您尝试写入超过 16k,则将需要 16k(最大记录大小)并从中创建一条 SSL 记录,该记录目前存储在 SSL 套接字中。然后它会尝试将此 SSL 记录写入底层套接字。

将完整 SSL 记录写入底层套接字可能不会立即成功,即可能只写入了部分记录。只要不是所有内容都写入内核套接字缓冲区,新创建的 SSL 记录中的一些尚未写入的数据将保留在 SSL 对象中缓冲。

只要 SSL 对象中的 SSL 记录仍有未写入的部分,进一步调用 SSL_write(强调 write_some)将仅尝试传递剩余数据,而不接受新数据。这就是返回 WOULD_BLOCK 的原因(这可能是从 SSL_write 返回的 SSL_WANT_WRITE 内部翻译的)。

© www.soinside.com 2019 - 2024. All rights reserved.