c++ - 在 Boost.Asio 请求期间检测中止的连接

标签 c++ sockets boost tcp boost-asio

<分区>

Possible Duplicate:
How to check if socket is closed in Boost.Asio?

在asio框架中是否有一种既定的方法可以在不发送任何数据的情况下确定TCP连接的另一端是否关闭?

将 Boost.asio 用于服务器进程,如果客户端在服务器响应请求之前超时或以其他方式断开连接,则服务器在完成请求并生成要发送的响应之前不会发现这一点,当发送立即产生连接中止错误时。

对于一些长时间运行的请求,这可能导致客户端取消并一遍又一遍地重试,堆积并行运行的同一请求的许多实例,使它们花费更长的时间并“滚雪球”成雪崩,使服务器无法使用。本质上,反复按 F5 是拒绝服务攻击。

不幸的是,在请求完成之前我无法开始发送响应,因此“流式传输”结果不是一种选择,我需要能够在请求处理期间的关键点进行检查,如果客户放弃了。

最佳答案

这个问题的关键是避免在接收处理程序中进行请求处理。以前,我在做这样的事情:

async_receive(..., recv_handler)

void recv_handler(error) {
    if (!error) {
        parse input
        process input
        async_send(response, ...)

相反,适当的模式更像这样:

async_receive(..., recv_handler)

void async_recv(error) {
    if (error) {
        canceled_flag = true;
    } else {
        // start a processing event
        if (request_in_progress) {
            capture input from input buffer
            io_service.post(process_input)
        }
        // post another read request
        async_receive(..., recv_handler)
    }
}

void process_input() {
    while (!done && !canceled_flag) {
        process input
    }
    async_send(response, ...)
}

显然我遗漏了很多细节,但重要的部分是将处理作为单独的“事件”发布到 io_service 线程池中,以便可以同时运行额外的接收。这允许在处理过程中接收“连接中止”消息。但是请注意,这意味着两个线程必须相互通信,需要某种同步,并且正在处理的输入必须与接收调用所在的输入缓冲区分开保存,因为更多数据可能会因到期而到达附加读取调用。

编辑:

我还应该注意,如果您在处理过程中收到更多数据,您可能不想启动另一个异步处理调用。稍后的处理可能会先完成,结果可能会乱序发送给客户端。除非您使用的是 UDP,否则这可能是一个严重的错误。

这是一些伪代码:

async_read (=> read_complete)
read_complete
    store new data in queue
    if not currently processing
         if a full request is in the queue
             async_process (=> process_complete)
    else ignore data for now
    async_read (=> read_complete)
async_process (=> process_complete)
    process data
process_complete
    async_write_result (=> write_complete)
write_complete
    if a full request is in the queue
        async_process (=> process_complete)

因此,如果在处理请求时收到数据,它会排队但不会被处理。一旦处理完成并发送结果,我们就可以使用之前收到的数据再次开始处理。

这可以通过允许在写入先前请求的结果时进行处理来进一步优化,但这需要更加小心以确保结果的写入顺序与收到的请求相同。

关于c++ - 在 Boost.Asio 请求期间检测中止的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2915332/

相关文章:

java - 为什么服务器没有收到客户端发送的对象?

c++ - 在协程执行之间强制休眠

c++ - 错误 C2664:无法将参数 1 从 'const std::basic_string<_Elem,_Traits,_Ax>' 转换为 'std::wstring &

c++ - QT https SSL 支持静态 QT 静态程序构建 - 仍然需要 openssl dll

c++ - Visual Express 与 Visual Studio

c - 两台64位机器之间的TCP套接字编程

c++ - 将带有迭代器的 C++ 程序转换为 Boost MPI 并行程序

java - 套接字连接问题

c++ - 使用 Boost 作为 CMake 的 git 子模块

python - Boost.Python python 链接错误