У меня есть приложение для потоковой передачи Perl, которое ПОЛУЧАЕТ какой-нибудь файл через HTTPS (для RadioParadise). Поток TCP часто приостанавливается на несколько секунд, потому что игрок много буферизует. В результате соединение очень часто разрывается / заканчивается рано.
Я взял различные протоколы TCP, и wireshark, кажется, все сбит с толку и жалуется на изменение спецификации шифра и игнорируемых неизвестных записей. Очевидно, что пакеты Change Cipher неверны и не соответствуют повторному установлению связи, в пакетах есть что-то смешное. То, что обязательно показывают журналы, в случае досрочного завершения, сервер закрывает соединение TCP (правильный кадр FIN)
Я написал небольшой пример Perl, который регулирует загрузку, используя паузы различной длины, чтобы показать, что происходит. Если загрузка не приостановлена более чем на 1 секунду, то этого не происходит. Когда он останавливается на 5 секунд, это всегда происходит в какой-то момент загрузки. OpenSSL сервера - 1.0.2k, и я попробовал клиент 1.1.0j и различные версии от 0.9.8 до 1.0.2. Я пробовал также различные версии Perl, без изменений
(это просто пример, который на самом деле показывает проблему, а не правильный код)
Я также написал то же приложение на C, чтобы исключить Perl как потенциальную проблему, и получил точно такой же результат.
Я также пробовал другие HTTPS-серверы, и у них нет такой же проблемы, похоже, это связано с RP. Может быть, у кого-то будет представление о том, на что мне следует обратить внимание при дальнейшем расследовании, поскольку в настоящее время я не знаю, в каком направлении продолжать. Несколько общих советов о том, почему приостановка на 5 секунд будет иметь какое-либо значение на уровне TCP или SSL (это не проблема SO_KEEPALIVE).
NB: в моем tcpdump нет пакетов, потерянных ядром
use IO::Socket::SSL;
use Net::SSLeay;
use IO::Select;
$IO::Socket::SSL::DEBUG = 3;
$Net::SSLeay::trace = 3;
my $sock = IO::Socket::SSL->new(
Timeout => 15,
PeerAddr => '23.29.117.2',
PeerPort => 443,
SSL_startHandshake => 1,
SSL_verify_mode => Net::SSLeay::VERIFY_NONE() # SSL_VERIFY_NONE isn't recognized on some platforms?!?, and 0x00 isn't always "right"
) or do {
print("Couldn't create socket binding to $!");
return undef;
};
my $sel = IO::Select->new($sock);
my $start = time;
use constant SLEEP => 5;
syswrite ($sock, "GET /blocks/chan/0/4/1835801-1835807.flac HTTP/1.0\r\n\r\n");
sysread( $sock, my $data, 512 );
print $data;
$sock->blocking(0);
my $total;
my $sum;
while (1) {
my $bytes = sysread( $sock, my $data, 8192 );
next if !defined $bytes;
last if !$bytes;
$total += $bytes;
$sum += $bytes;
print "$total ", int ($total/(time() - $start)/1000), " kB/s \r" if time() - $start;
if ($sum > SLEEP*1024*1024/8) {
sleep(SLEEP);
$sum = 0;
}
}
print("\nfinished $total\n");
$sock->close();