Как вы делаете тайм-аут постоянных / поддерживающих SSL-соединений с блокирующими сокетами? - PullRequest
2 голосов
/ 12 июля 2011

A предыдущий вопрос спросил, если изменение одной строки кода реализовало постоянные соединения SSL.После просмотра ответов на этот вопрос и проверки недостатка документации по SSL, вы увидите следующее:

  • для сервера, постоянное соединение просто выполняет повторные запросы / ответы между SSL_accept () иSSL_set_shutdown ().

  • согласно этой странице , клиент должен указать, сколько запросов будет, отправив соответствующий заголовок «Content-length:» илииспользуя согласованный завершающий запрос.

Однако нет никакой гарантии, что клиент отправит то, что он должен.Следовательно, может показаться, что сервер, использующий блокирующие сокеты, может бесконечно зависать на SSL_read (), ожидая дополнительных запросов, которые никогда не поступают.(Похоже, что SSL_CTX_set_timeout () не приводит к преждевременному завершению последующего SSL_read (), поэтому неясно, как выполнять тайм-аут соединения, как описано на этой странице Википедии , если сокеты блокируются.)

Судя по всему, сервер может указать, что он не будет поддерживать работу, возвращая заголовок «Connection: Close» с ответом, поэтому я получил следующий код, который, по крайней мере, всегда должен правильно выполнятьодин запрос / ответ на соединение:

while TRUE do
  begin  // wait for incoming TCP connection
  if notzero(listen(listen_socket, 100)) then continue; // listen failed
  client_len := SizeOf(sa_cli);
  sock := accept(listen_socket, @sa_cli, @client_len); // create socket for connection
  if sock = INVALID_SOCKET then continue; // accept failed
  ssl := SSL_new(ctx); // TCP connection ready, create ssl structure
  if assigned(ssl) then
    begin
    SSL_set_fd(ssl, sock); // assign socket to ssl structure
    if SSL_accept(ssl) = 1 then // handshake worked
      begin
      request := '';
      repeat // gather request
        bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
        if bytesin > 0 then
          begin
          buffer[bytesin] := #0;
          request := request + buffer;
          end;
      until SSL_pending(ssl) <= 0;
      if notempty(request) then
        begin // decide on response, avoid keep-alive
        response := 'HTTP/1.0 200 OK'#13#10'Connection: Close'#13#10 + etc;
        SSL_write(ssl, pchar(response)^, length(response));
        end; // else read empty or failed
      end; // else handshake failed
    SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN or SSL_RECEIVED_SHUTDOWN);
    CloseSocket(sock);
    SSL_free(ssl);
    end; // else ssl creation failed
  end; // infinite while

Два вопроса:

(1) Поскольку SSL_accept () должен быть истинным для достижения SSL_read (), верно ли это, SSL_read () никогда не может зависнутьв ожидании первого запроса?

(2) Как этот код следует изменить, чтобы сделать постоянными тайм-ауты / поддерживать SSL-соединения с блокирующими сокетами (если это возможно)?

Ответы [ 2 ]

1 голос
/ 14 августа 2011

Цитируя это письмо , «Единственный способ избежать неопределенной блокировки - это использовать неблокирующий ввод / вывод».Итак, я думаю, что я перестану пытаться тайм-аут заблокированных SSL_read () с.

0 голосов
/ 14 июля 2011

(1), если клиент подключается, но не отправляет запрос (например, DoS-атака), SSL_read () зависает.

(2) попробуйте вызвать setsockopt(SO_RCVTIMEO) на принятом SOCKET, чтобы установить для него тайм-аут чтения.

...