Posso detectar quando um cliente se desconectou de um CGI?

Posso detectar quando um cliente se desconectou de um CGI?

Eu tenho um CGI que consome muitos recursos e leva muito tempo para começar a enviar dados. Vimos alguns casos em que pessoas impacientes recarregam algumas vezes, o que aciona o carregamento de execuções adicionais do CGI, ou casos em que o cliente atinge o tempo limite e interrompe a conexão, mas o CGI continua funcionando.

Existe alguma boa maneira de detectar quando isso aconteceu? Ele nem precisa estar dentro do próprio CGI (e provavelmente é melhor se não estiver - ele passa para outro programa sobre o qual não tenho controle), mas pode ser um cron job executado de vez em quando procurar conexões mortas para colher.

Atualmente estou usando o Apache, mas este é um problema tão grande que eu estaria disposto a executar algum outro servidor web se ele tivesse provisões para lidar com isso (ou uma maneira de me permitir monitorar o problema).

Responder1

Normalmente, você não consegue detectar a conexão interrompida até começar a responder ao usuário. Caso contrário, seu processo continuará fazendo seu trabalho sem perceber a interrupção da conexão do lado do usuário.Esta postagemestá relacionado mesmo que fale sobre PHP. O conceito deveria ser o mesmo.

Existem coisas possíveis que você pode tentar:

  1. Faça o trabalho demorado em segundo plano. Quando um usuário solicitar o CGI, não execute a tarefa como uma chamada de bloqueio normal. Basta retornar qualquer coisa ao usuário para informar que a solicitação está em processamento. Obviamente, você precisa encontrar uma maneira de atualizar a visualização ou fornecer outra página para verificar o status do trabalho usando algum ID ou IP de solicitação.
  2. Envie os dados de volta ao cliente o mais rápido possível e saia se o envio falhar (indicação de conexão interrompida). Você pode, por exemplo, enviar o progresso do trabalho a cada poucos segundos ou minutos.

Se você salvar os trabalhos atualmente em execução em um banco de dados, poderá salvar o ID da solicitação e/ou o endereço IP do cliente. Assim, você pode detectar e ignorar solicitações duplicadas para o mesmo recurso informando ao usuário "sua solicitação está em processamento".

Responder2

Atenção: esta informação pode estar obsoleta. Veja o último parágrafo.

Lembro-me de ter tido o mesmo problema e de resolvê-lo com umnph(sem cabeçalho de análise) Script CGI.

Normalmente, o Apache coleta todos os cabeçalhos do seu script e, quando termina de ler os cabeçalhos, altera-os com alguns cabeçalhos padrão que você não forneceu. O que também significa que, desde que você não termine os cabeçalhos, o Apache não enviará nada ao cliente.

Com um script nph, você terá que fornecer todos os cabeçalhos, mas o Apache os enviará ao cliente imediatamente e enviará ao seu script CGI um SIGPIPE assim que o cliente se desconectar. Assim, você pode enviar algum X-Slowly-Counting-Part-nnn: yescabeçalho a cada poucos segundos, para evitar tempos limite no cliente, e será notificado se os clientes interromperem a conexão.

Isso ainda deixa o problema, você terá que enviar o status HTTP primeiro, mas se você enviar um 'Content-Length: 0', ou talvez um 'Content-Length: 1' e fechar a conexão sem enviar nenhum conteúdo, seu arquivo baixadordeveassuma um erro de rede e aja de acordo.

Você provavelmente terá que canalizar a saída do outro programa através do seu processo, mas isso não deve ser um grande impacto no desempenho, pelo menos se você estiver no Linux e usar a sendfile(2)chamada do sistema.

O problema com tudo isso é que eu o usei há pelo menos 10 anos, provavelmente no Apache 1.3, e pesquisar no Google apache cgi nphnão rendeu nada de útil. Então, talvez o recurso nph tenha sido retirado entretanto - mas talvez não, admito que não procurei muito.

Responder3

Pergunta antiga, mas tive o mesmo problema e resolvi verificar se a conexão está estabelecida:

No meu caso, estou executando um script bash no servidor.. as variáveis ​​​​env são exportadas por mod_cgi. Acredito que esta solução funcionará para qualquer programa/script rodando em CGI

ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
     # Client closed browser/connection
fi

informação relacionada