#perl #websocket
#perl #websocket
Вопрос:
Я пытаюсь создать простой сервер WebSocket на perl с нуля, когда я попробовал это в Google Chrome, он выдал мне код операции -1, как я могу это исправить?
websocket.pl
#!/usr/bin/perl -w
use strict;
use IO::Socket::INET;
use Digest::SHA1 "sha1_base64";
$| = 1;
my $magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
# Create a server
my $socket = IO::Socket::INET->new( LocalHost => 'localhost',
LocalPort => 7777,
Proto => 'tcp',
Listen => 5,
Reuse => 1
) || die "$!";
print "Server is running on port 7777n";
while (1) {
my $client = $socket->accept();
my $key = "";
# Get the Request
my $data = "";
while (my $line = <$client>) {
$data .= $line;
}
# Get the Sec-WebSocket-Key value
foreach my $line ( split /n/ => $data ) {
if ( $line =~ /^Sec-WebSocket-Key: (S )/ ) {
$key = $1;
}
}
print "Sec-WebSocket-Key: $keyn";
# Create the Sec-WebSocket-Accept header value
my $accept = sha1_base64($key);
$accept .= "="x(4-(length($accept)%4));
print "Sec-WebSocket-Accept: $acceptn";
# Response
print $client "HTTP/1.1 101 Switching Protocolsrn";
print $client "Upgrade: websocketrn";
print $client "Connection: Upgradern";
print $client "Sec-WebSocket-Accept: $acceptrnrn";
shutdown($client, 1);
}
$socket->close();
Я почти уверен, что ключ, возвращенный на веб-сайт, правильный, так в чем же проблема? Что пошло не так?
ws.js
var ws = new WebSocket("ws://localhost:7777/");
ws.onopen = function() {
alert("connected!");
ws.send( 'Hello server' );
};
ws.onclose = function() {
alert( 'Connection is closed... ');
};
Редактировать
Стефан Беккер: Да, я знаю, но в данном случае я был уверен, что запрос меньше 1024 байт, я это исправил, спасибо.
Комментарии:
1.
recv
не гарантирует, что данные будут прочитаны одним фрагментом: »recv SOCKET,SCALAR,LENGTH,FLAGS
Получает сообщение на сокете. Пытается преобразовать символы длины данных в переменную SCALAR из указанного дескриптора файла СОКЕТА . СКАЛЯР будет увеличен или уменьшен до фактически прочитанной длины.» При обработке HTTP вы должны выполнять цикл до тех пор, пока не получите все данные (заголовок тело длины содержимого), прежде чем обрабатывать запрос.2. Почему бы вам не избежать всех хлопот с разбором HTTP-запроса и позволить Net::Server:: HTTP выполнять всю работу? Вам просто нужно написать обработчик запроса. Возможно, вам также следует заглянуть в Net::WebSocket …
3. Стефан Беккер: Потому что мне нравится использовать сокеты (Да, я знаю, что это не так эффективно или быстро, как использование модуля для этого). Да, я использую Net::WebSocket в облаке, но я просто хочу углубиться в это.
Ответ №1:
(Код операции -1) является общей ошибкой. В вашем случае это неправильный Sec-WebSocket-Accept
заголовок. Вы забыли использовать $magic_string
:
my $accept = sha1_base64($key.$magic_string);
Также while (my $line = <$client>) {
, вероятно, будет выполняться вечно. Вам нужно проверить наличие пустой строки.
Комментарии:
1.
while (my $line = <$client>) {
Работает нормально, это так же, как при чтении файла, но спасибо за ответ, это сработало.