检测Boost.Asio的请求期间中止连接 [英] Detect aborted connection during Boost.Asio request

查看:112
本文介绍了检测Boost.Asio的请求期间中止连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  如何检查是否套接字在Boost.Asio的关闭?

是否有既定的方式来确定不发送任何数据是否TCP连接的另一端在ASIO框架是封闭

Is there an established way to determine whether the other end of a TCP connection is closed in the asio framework without sending any data?

使用Boost.Asio的一个服务器处理中,如果客户端倍服务器之前,或以其他方式断开已经响应的请求时,服务器不直到它已完成该请求,并产生一个响应于发送发现这一点,当发送立即生成一个连接中断错误。

Using Boost.asio for a server process, if the client times out or otherwise disconnects before the server has responded to a request, the server doesn't find this out until it has finished the request and generated a response to send, when the send immediately generates a connection-aborted error.

对于一些长时间运行的请求,这可能会导致客户取消和重试了个遍,堆放在并行运行的同一请求的多个实例,让他们甚至需要更长的时间和滚雪球到雪崩,使得服务器无法使用。基本上按F5遍地是拒绝服务攻击。

For some long-running requests, this can lead to clients canceling and retrying over and over, piling up many instances of the same request running in parallel, making them take even longer and "snowballing" into an avalanche that makes the server unusable. Essentially hitting F5 over and over is a denial-of-service attack.

可惜我不能开始发送一个响应,直至请求完成,那么流的结果出来是不是一种选择,我需要能够在关键点请求处理过程中,检查,制止处理,如果客户已经放弃了。

Unfortunately I can't start sending a response until the request is complete, so "streaming" the result out is not an option, I need to be able to check at key points during the request processing and stop that processing if the client has given up.

推荐答案

这个问题的关键是要避免在接收处理程序做请求处理。 previously,我在做这样的事情:

The key to this problem is to avoid doing request processing in the receive handler. Previously, I was doing something like this:

async_receive(..., recv_handler)

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

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

Instead, the appropriate pattern is more like this:

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对象线程池中的一个单独的事件,让一个额外的接收可以同时运行。这允许在处理过程中要接收的连接中断的消息。要注意,然而,这意味着两个线程必然互相需要某种同步而这被处理必须从到其中的接收呼叫被放置,因为更多的数据可能会由于到达输入缓冲器分开保存的输入通信到附加读通话。

Obviously I have left out lots of detail, but the important part is to post the processing as a separate "event" in the io_service thread pool so that an additional receive can be run concurrently. This allows the "connection aborted" message to be received while processing is in progress. Be aware, however, that this means two threads must necessarily communicate with each other requiring some kind of synchronization and the input that's being processed must be kept separately from the input buffer into which the receive call is being placed, since more data may arrive due to the additional read call.

编辑:

我还要指出的是,你应该得到更多的数据,而处理正在发生的事情,你可能不希望启动另一个异步处理呼叫。这是可能的,这以后的处理可以首先完成,并且结果可以被发送到客户端外的顺序。除非你使用UDP,这可能是一个严重的错误。

I should also note that, should you receive more data while the processing is happening, you probably do not want to start another asynchronous processing call. It's possible that this later processing could finish first, and the results could be sent to the client out-of-order. Unless you're using UDP, that's likely a serious error.

下面是一些伪code:

Here's some pseudo-code:

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)

因此​​,如果接收数据,而一个请求是在过程中,它的排队,但不处理。一旦处理完成,结果被发送,那么我们可以开始与先前接收到的数据重新处理

So, if data is received while a request is in process, it's queued up but not processed. Once processing completes and the result is sent, then we may start processing again with the data that was received earlier.

这可以更通过允许同时previous请求的结果被写入到发生处理进行优化了一点,但是这需要更小心以确保该结果被写入的相同顺序的请求是收到。

This can be optimized a bit more by allowing processing to occur while the result of the previous request is being written, but that requires even more care to ensure that the results are written in the same order as the requests were received.

这篇关于检测Boost.Asio的请求期间中止连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆