Сервер OpenSSL не может обработать разъединение клиента с задержками между записями - PullRequest
0 голосов
/ 03 марта 2019

Я новичок в программировании OpenSSL.В любом случае, я написал сервер и клиент openssl на C (также протестирован на C ++).Когда они соединяются, они успешно рукопожатие и могут читать и писать друг другу успешно.В настоящее время он настроен так, что клиент читает только из потока и записывает в буфер, например:

while((rc = SSL_read(ssl, buffer, sizeof(buffer))) > 0){
    fprintf(stdout,"%s\n", buffer);
}

Аналогично, мой сервер настроен так, что он постоянно записывает в поток из буфера, например:

while ((rc = SSL_write(ssl, buffer, sizeof(buffer))) > 0) {
    fprintf(stdout, "Sent message.\n");
}
fprintf(stdout, "Done sending.\n");

И это работает.Если бы я внезапно завершил работу клиента с помощью ^C (Ctrl C), сервер завершил бы работу и напечатал «Done Sending».Однако, если бы я поместил задержку дольше, чем около 10000 наносекунд между каждым SSL_write (в рамках цикла записи сервера), я получаю неожиданное поведение, когда клиент отключается внезапно (используя ^C) или обычно через счетчик и разрыв.Для пояснения, перед внезапным отключением сервер может использовать SSL_write, а клиент может использовать SSL_read в обычном режиме между любыми задержками (ничего не пытался в течение минуты).

Эта проблема означает, что клиентское соединениеможет эффективно привести к аварийному завершению потока сервера, о чем свидетельствует отсутствие печати «Готово к отправке» после отключения клиента при использовании задержек, превышающих 10000 наносекунд.Я не хочу, чтобы сервер был в состоянии сбоя из-за внезапного отключения в сеансе.Чтобы было ясно, что сервер вылетает при вызове SSL_write и ничего не возвращает.

Я пытался решить эту проблему:

  • Попытка увидеть изменения в этих возвратахзначения: SSL_want(ssl), SSL_get_error(ssl,0), ERR_get_error() и SSL_get_shutdown(ssl).В некотором тестовом коде я распечатал все это до вызова SSL_write, и ни один из них не изменил свои значения перед сбоем.
  • Очистка очереди ошибок перед каждым SSL_write с использованием ERR_clear_error()
  • Проверка того, напечатано ли что-нибудь с помощью ERR_print_errors_fp(stderr) - nada

Я использовал следующие методы задержки:

// Method 1
for(long i = 0; i < (long) 99999999; i++){}

// Method 2
struct timespec tim, tim2;
tim.tv_sec = 0;
tim.tv_nsec = 10000L; // 5 milliseconds
nanosleep(&tim, &tim2);

// Method 3
sleep(1)

Лично я считаю, что было бы нелепо требовать, чтобызапись в сокет в течение одной сотой миллисекунды, чтобы сервер не зависал при отключении клиента.

Это действительно ожидаемое поведение?Я делаю что-то не так или я что-то забываю?Что я должен сделать, чтобы обойти эту проблему?

Буду признателен за любую помощь или совет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...