Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ t该选项仅影响执行套接字I/O的系统调用,例如read()和recvmsg()。它不会影响事件解复用器,例如select()和poll(),这些事件解复用器仅监视文件描述符以确定何时可以在不阻塞的情况下发生I/O。此外,当超时发生时,I/O调用无法返回-1,并将errno设置为EAGAIN或ewoodblock_C++_Linux_Boost_Boost Asio - Fatal编程技术网

C++ t该选项仅影响执行套接字I/O的系统调用,例如read()和recvmsg()。它不会影响事件解复用器,例如select()和poll(),这些事件解复用器仅监视文件描述符以确定何时可以在不阻塞的情况下发生I/O。此外,当超时发生时,I/O调用无法返回-1,并将errno设置为EAGAIN或ewoodblock

C++ t该选项仅影响执行套接字I/O的系统调用,例如read()和recvmsg()。它不会影响事件解复用器,例如select()和poll(),这些事件解复用器仅监视文件描述符以确定何时可以在不阻塞的情况下发生I/O。此外,当超时发生时,I/O调用无法返回-1,并将errno设置为EAGAIN或ewoodblock,c++,linux,boost,boost-asio,C++,Linux,Boost,Boost Asio,指定接收或发送超时,直到报告错误。[…]如果未传输数据且已达到超时,则返回-1,并将errno设置为EAGAIN或ewoodblock[…]超时仅对执行套接字I/O的系统调用有效(例如,read(),recvmsg(),[…];超时对select()无效)、poll()、epoll\u wait(),等等 当底层文件描述符设置为非阻塞时,执行套接字I/O的系统调用将立即返回EAGAIN或ewoodblock,如果资源不立即可用。对于非阻塞套接字,SO_RCVTIMEO将不会有任何影响,因为调用将

指定接收或发送超时,直到报告错误。[…]如果未传输数据且已达到超时,则返回
-1
,并将errno设置为
EAGAIN
ewoodblock
[…]超时仅对执行套接字I/O的系统调用有效(例如,
read()
recvmsg()
,[…];超时对
select()无效)
poll()
epoll\u wait()
,等等

当底层文件描述符设置为非阻塞时,执行套接字I/O的系统调用将立即返回
EAGAIN
ewoodblock
,如果资源不立即可用。对于非阻塞套接字,
SO_RCVTIMEO
将不会有任何影响,因为调用将立即返回并成功或失败失败。因此,要使
SO\u RCVTIMEO
影响系统I/O调用,套接字必须阻塞

助推,助推行为 首先,Boost.Asio中的异步I/O操作将使用事件解复用器,例如
select()
poll()
。因此,
SO\u RCVTIMEO
不会影响异步操作

接下来,Boost.Asio的套接字具有两种非阻塞模式的概念(都默认为false):

  • 大致对应于文件描述符的非阻塞状态的模式。此模式影响系统I/O调用。例如,如果调用
    socket.native\u non\u blocking(true)
    ,则调用
    recv(socket.native\u handle(),…)
    如果将
    errno
    设置为
    EAGAIN
    eWoldBlock
    ,则可能会失败。只要在套接字上启动异步操作,Boost.Asio就会启用此模式
  • 影响Boost.Asio的同步套接字操作的模式。当设置为
    true
    时,Boost.Asio会将基础文件描述符设置为非阻塞和同步Boost。Asio套接字操作可能会因
    Boost::Asio::error::will_block
    (或等效的系统错误)而失败。当设置为
    false
    时,Boost.Asio将通过轮询文件描述符并在返回
    EAGAIN
    ewoodblock
    时重新尝试系统I/O操作来阻止,即使底层文件描述符是非阻塞的
non\u blocking()
的行为会阻止
SO\RCVTIMEO
产生所需的行为。假设调用了
socket.receive()
,并且数据既不可用也不接收:

  • 如果
    non_blocking()
    为false,系统I/O调用将根据
    SO\u RCVTIMEO
    超时。但是,Boost.Asio随后将立即阻止对文件描述符的轮询以使其可读,这不受
    SO_RCVTIMEO
    的影响。最终结果是在
    套接字中阻止调用方。receive()
    直到收到数据或出现故障,如远程对等方关闭连接
  • 如果
    non\u blocking()
    为true,则底层文件描述符也是非阻塞的。因此,系统I/O调用将忽略
    SO\u RCVTIMEO
    ,立即返回
    EAGAIN
    ewoodblock
    ,导致
    socket.receive()
    boost::asio::error::will\u block
    而失败
理想情况下,要使
SO\u RCVTIMEO
与Boost.Asio一起工作,需要将
native\u non\u blocking()
设置为false,以便
SO\u RCVTIMEO
能够生效,但也需要将
non\u blocking()
设置为true,以防止对描述符进行轮询。但是,Boost.Asio没有:

socket::本机非阻塞(bool模式)

如果模式为
false
,但
non_blocking()
的当前值为
true
,此函数将失败,并出现
boost::asio::error::invalid_参数
,因为组合没有意义


谢谢你提醒我。但即使我不能使用SO_RCVTIMEO async_,也会收到规定的超时。@fneig请尝试编辑后的答案并让我知道:)我不能说我完全理解实现,但感觉它可以正常工作。它调用套接字上的recv,该套接字可能会返回超时。然后,不调用poll,只返回超时错误。至少在windows上,设置SO_RCVTIMEO确实有效(简单地说,没有设置非阻塞模式等),至少在boost 1.64中是有效的,并且只做您所期望的。不知道为什么目前在非Windows平台上没有。
boost::asio::io_service io;
boost::asio::ip::tcp::acceptor::reuse_address option(true);
boost::asio::ip::tcp::acceptor accept(io);
boost::asio::ip::tcp::resolver resolver(io);
boost::asio::ip::tcp::resolver::query query("0.0.0.0", "8080");
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
accept.open(endpoint.protocol());
accept.set_option(option);
accept.bind(endpoint);
accept.listen(30);

boost::asio::ip::tcp::socket ps(io);

accept.accept(ps);

struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
//setsockopt(ps.native(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
setsockopt(ps.native(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
char buf[1024];
ps.async_receive(boost::asio::buffer(buf, 1024), boost::bind(fun));
io.run();
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>

void myclose(boost::asio::ip::tcp::socket& ps) { ps.close(); }

int main()
{
  boost::asio::io_service io;
  boost::asio::ip::tcp::acceptor::reuse_address option(true);
  boost::asio::ip::tcp::acceptor accept(io);
  boost::asio::ip::tcp::resolver resolver(io);
  boost::asio::ip::tcp::resolver::query query("0.0.0.0", "8080");
  boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
  accept.open(endpoint.protocol());
  accept.set_option(option);
  accept.bind(endpoint);
  accept.listen(30);
  boost::asio::ip::tcp::socket ps(io);
  accept.accept(ps);
  char buf[1024];
  boost::asio::deadline_timer timer(io, boost::posix_time::seconds(1));
  timer.async_wait(boost::bind(myclose, boost::ref(ps))); 
  ps.async_receive(boost::asio::buffer(buf, 1024),
           [](const boost::system::error_code& error,
              std::size_t bytes_transferred )
           {
             std::cout << bytes_transferred << std::endl;
           });
  io.run();
  return 0;
}