跨平台(Linux/Win32)的C++非阻塞IO在标准输入/输出/错误上。

10

我正在尝试寻找一种通过stdin/stdout实现非阻塞IO的最佳解决方案,具有以下特征:

  • 只要有足够的数据,就以n字节大小的块来读取。
  • 如果没有足够的数据,则读取部分块。
  • 如果没有可用的数据,则阻塞直到有一些数据(即使它可能小于n)。

目标是允许大数据集的高效传输,同时立即处理'控制'代码(而不是让它们在某个部分填充的缓冲区中逗留)。

我知道可以通过使用线程和istream::get()循环或编写一堆平台特定的代码来实现这一点(因为你不能在Windows上选择文件句柄)... (还有看起来很有前途的istream::readsome(),但我在谷歌上找到的唯一结果是人们说它实际上并不好用。)

由于我没有使用这些API进行过多的编码,也许有更好的方法。

3个回答

7
也许您可以使用boost::asio来帮助您解决问题?

看起来相当有前途(大材小用,但学起来可能很值得)...谢谢! - Dan S.
是的,这可能是您实现可移植异步I/O的最佳选择,因为该语言不支持非阻塞I/O或线程。您将需要使用某种库,而boost通常是一个不错的选择。 - jalf
如果Win32支持在任意句柄上使用select()或poll()而不仅仅是套接字,那就好了...经过一番搜索,我确认我可以做到我需要的,并且甚至有一个设置教程:http://www.highscore.de/boost/process/process/tutorials.html#process.tutorials.async_io - Dan S.
附加说明:本教程旨在使用异步流捕获子进程的stdin/stdout;我想要的是让我的进程以异步方式处理自己的stdin/stout。尽管如此,这仍然是一个很好的解决方案,已经完成了90%的工作。 - Dan S.
@DanS.:你有找到100%的解决方案吗?我现在正在尝试解决同样的问题(https://dev59.com/m2TWa4cB1Zd3GeqPF7by)。 - John Dibling

2

我使用了线程和特定于平台的代码。请参见我在另一个问题中的答案。我能够将特定于操作系统的东西放在inputAvailable()方法中(Linux使用select,Windows只返回true)。然后,我可以在Windows上使用WaitForSingleObject()来尝试让线程完成,然后使用TerminateThread()来终止它。非常丑陋,但团队不想使用这个boost。


这只是链接到一个非跨平台的解决方案(还包括一些过时的链接)。你有原始实现可用吗? - helmesjo
1
抱歉,那是以前的公司,我不再拥有那段代码。我相信inputAvailable()的代码是Linux解决方案。作为Windows的起点,请查看_kbit():https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/kbhit?view=vs-2019 - jwhitlock

0

我做了类似于jwhitlock的事情...最终我得到了一个StdinDataIO类,它包装了适当的操作系统特定实现(*),以便我的程序的其余部分可以选择() StdinDataIO提供的文件描述符,对Windows关于stdin的限制保持无知。如果你愿意,可以在这里这里看看,代码都是开源/ BSD许可证。

(*) 实现对于Linux/MacOSX来说是一个简单的通过,而在Windows中,它是一个相当复杂的过程,需要设置一个子线程从stdin读取数据,并将接收到的数据通过套接字发送回主线程...不是非常优雅,但它能工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接