Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > клиент-сервер. серверная часть perl


Автор: Bulat 5.7.2013, 20:39
На стороне клиента простой html, javascript и websocket. Например:
Код

function WebSocketTest()
{
  if ("WebSocket" in window)
  {
     alert("WebSocket is supported by your Browser!");
     // Let us open a web socket
     var ws = new WebSocket("ws://localhost:9998/echo");
     ws.onopen = function()
     {
        // Web Socket is connected, send data using send()
        ws.send("Message to send");
        alert("Message is sent...");
     };
     ws.onmessage = function (evt) 
     { 
        var received_msg = evt.data;
        alert("Message is received...");
     };
     ws.onclose = function()
     { 
        // websocket is closed.
        alert("Connection is closed..."); 
     };
  }
  else
  {
     // The browser doesn't support WebSocket
     alert("WebSocket NOT supported by your Browser!");
  }
}

WebSocketTest();


Очень хотелось бы посмотреть тривиальную реализацию сервера на перл. Желательно через бифы(socket).

Автор: Bulat 6.7.2013, 09:07
Вот что я имею на данный момент, если более подробно:

test.html:

Код

<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    </head>
    <body>
        <script type="text/javascript">
        </script>
        <table border="0" cellpadding="2" cellspacing="2" width="100%">
            <tr>
                <td align="center">
                    <script type="text/javascript">

function WebSocketTest()
{
  if ("WebSocket" in window)
  {
     alert("WebSocket is supported by your Browser!");
     // Let us open a web socket
     var ws = new WebSocket("ws://localhost:8888/");
     ws.onopen = function()
     {
        // Web Socket is connected, send data using send()
        ws.send("Message to send");
        alert("Message is sent...");
     };
     ws.onmessage = function (evt) 
     { 
        var received_msg = evt.data;
        alert("Message is received...");
     };
     ws.onclose = function()
     { 
        // websocket is closed.
        alert("Connection is closed..."); 
     };
  }
  else
  {
     // The browser doesn't support WebSocket
     alert("WebSocket NOT supported by your Browser!");
  }
}

WebSocketTest();

                        </script>
                </td>
            </tr>
        </table>
    </body>
</html>


websocket_server.pl :

Код

#!/usr/bin/perl

use strict;

use IO::Socket::INET;
use IO::Select;
use Carp;

my $Port = 8888;

my $Listen = IO::Socket::INET->new(
    Listen    => 5,
    LocalPort => $Port,
    Proto     => 'tcp',
    ReuseAddr => 1,
) or croak "failed to listen on port $Port: $!";

my $Select = IO::Select->new($Listen);

while ($Select -> count) {
    my @ready = $Select -> can_read();

    foreach my $fh (@ready) {
        if ($fh == $Listen) {
            my $sock = $Listen -> accept;

            my ($len, $data) = (0, "");

            $len = sysread($sock, $data, 8192, length($data));

            print $data, "\n";
        } else {
        }
    }
}


В браузере выдает: Connection is closed...

А скрипт пишет заголовок:
Код

GET / HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: null
Sec-WebSocket-Key: sH68KCt1RlVBv4tH8tz8Sg==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket


Помогите докрутиить, а, эту фичу...

Ну идея банально простая... Типичный клиент-сервер..... Тока технически нужно дожать и все...

Автор: Pilat66 6.7.2013, 09:49
Сделайте это с Mojolicious и не мучайтесь.

Автор: Bulat 6.7.2013, 10:19
Цитата(Pilat66 @  6.7.2013,  09:49 Найти цитируемый пост)
Сделайте это с Mojolicious и не мучайтесь. 


А можно ответтить на вопрос который интересует меня, подчеркиваю?? =)

Автор: arto 8.7.2013, 08:10
вы с самим протоколом разобрались?
тогда можете посмотреть тут: http://cpansearch.perl.org/src/MIYAGAWA/Twiggy-0.1021/eg/chat-websocket/chat.psgi,
достаточно простая реализация.

Автор: Bulat 8.7.2013, 10:41
arto, ну вот сижу ковыряюсь... по ссылке пока просмотрел по диагонали, но чуть позже гляну подробнее... Вроде как раз в ту сторону что мне и нужно было. smile 

Автор: Bulat 9.7.2013, 22:21
Код

#!/usr/bin/perl
use strict;

use Socket;
use Carp;

sub logmsg { print "@_ \n" }

my $port = shift || 8888;
my $proto = getprotobyname('tcp');

($port) = $port =~ /^(\d+)$/ or die "invalid port";

socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))   || die "setsockopt:$!";
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";

my $paddr;

$SIG{CHLD} = \&REAPER;

for ( ; $paddr = accept(Client,Server); close Client) {
    my($port,$iaddr) = sockaddr_in($paddr);
    my $name = gethostbyaddr($iaddr,AF_INET);

    my ($len, $data) = (0, "");

    $len = sysread(Client, $data, 8192, length($data));

    logmsg $data;

    my $Key;

    my $SecretKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    if ($data =~ /Sec-WebSocket-Key: (.*?)\r/) {

        my $data = $1.$SecretKey;

        use Digest::SHA1 qw/sha1_base64/;

        $Key = sha1_base64($data);

    }

    my $SendHandshake = "HTTP/1.1 101 Switching Protocols\r\n".
    "Upgrade: websocket\r\n".
    "Connection: Upgrade\r\n".
    "Sec-WebSocket-Accept: $Key\r\n\r\n";

    logmsg $SendHandshake;

    print Client $SendHandshake;
}


Код

<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    </head>
    <body>
        <script type="text/javascript">
        </script>
        <table border="0" cellpadding="2" cellspacing="2" width="100%">
            <tr>
                <td align="center">
                    <script type="text/javascript">

function WebSocketTest()
{
  if ("WebSocket" in window)
  {
     alert("WebSocket is supported by your Browser!");
     // Let us open a web socket
     var ws = new WebSocket("ws://localhost:8888");
     ws.onopen = function()
     {
        //Web Socket is connected, send data using send()
                alert("Message is sent...");
        ws.send("Message to send");
     };

     //alert(ws.readyState);

     //ws.send('meaasge');

     ws.onmessage = function (evt) 
     { 
        var received_msg = evt.data;
        alert("Message is received...");
     };

     ws.onclose = function()
     { 
         //websocket is closed.
        alert("Connection is closed..."); 
     };
  }
  else
  {
     // The browser doesn't support WebSocket
     alert("WebSocket NOT supported by your Browser!");
  }
}

WebSocketTest();

                        </script>
                </td>
            </tr>
        </table>
    </body>
</html>


Вот, что я имею на данный момент, но onopen все равно не срабатывает....

Пробовал по-разному ответный хендшейк формировать, но пока так успеха и не добился... В чем проблема - не вижу!

Автор: arto 10.7.2013, 06:46
onopen -- это javascript?

Автор: Bulat 10.7.2013, 07:24
Цитата(arto @  10.7.2013,  06:46 Найти цитируемый пост)
onopen -- это javascript? 


Угу.

В приведеннем мною примере javascript выводит два сообщения. Сначала

WebSocket is supported by your Browser!

потом

Connection is closed...

А хочется чтоб хотя бы раз написал

Message is sent...

Автор: arto 10.7.2013, 08:38
порты открыты?

Автор: Bulat 10.7.2013, 16:52
Цитата(arto @  10.7.2013,  08:38 Найти цитируемый пост)
порты открыты? 

само собой.
От клиента(javascript) я хендшейк-то получаю. А вот ответный хендшейк почему-то не срабатывает

Код

GET / HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: null
Sec-WebSocket-Key: bPrv+i5TCC1vR/tObh8wCw==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: SL2qAawt3BX3DYVcQvXWOgB3DWE

Автор: Bulat 12.7.2013, 06:25
проблема решена, пример реально работающего хендшейка:
Код

my $SendHandshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n".
"Upgrade: WebSocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Accept: $Key=\r\n".
"\r\n";


Недочеты заключается:
1. в рфс описывается Switching Protocols, а нужно на самом деле Web Socket Protocol Handshake
2. При формировании ответного ключа необходимо дополнять символом '=', и действительно в примерах так оно и укаано, а в описании я об этом ничего не нашел
3. Символы переноса строик и возврата каретки. И здесь тоже изначально трактуется как бы само собой разумеющееся, однако были сомнения, потому что нигде конкретно это не описывается

Автор: arto 12.7.2013, 07:42
1. RFC 6455 1.2.  Protocol Overview: The protocol has two parts: a handshake and the data transfer.

2. RFC 6455 1.2.  Protocol Overview: The handshake from the server looks as follows:

        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat

3. RFC 2616 2.2 Basic Rules: HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all protocol elements except the entity-body.


"читайте документацию -- она рулез" (ц) чей-то

Автор: Bulat 12.7.2013, 14:46
arto, дословно перевести??

1. Протокол состоит из двух частей: хендшейк и данные
2. Хендшейк от сервера должен выглядить следующим образом(и тут же кстати как раз и неверный хендшейк)

Дальше продолжать??

P.S. Давай не будем устраивать холивар, я в интернете нашел уже несколько статей, подобному моему топику, где разные программисты точно так же описывали с какими трулностями они столкнулись при реализации вебсокеты, жалобы на плохо описанный стандарт есть.

всегда есть куда расти (с)

Автор: arto 13.7.2013, 11:43
1. ну. в рфц присутствует описание протокола. или описание handshake там отсутствует?

2. а что там именно неверно?

3. по третьему пункту вопросов, как я понимаю, нет?

пс. дамп хендшейка с http://www.websocket.org/echo.html:
Hypertext Transfer Protocol
    HTTP/1.1 101 Web Socket Protocol Handshake\r\n
        [Expert Info (Chat/Sequence): HTTP/1.1 101 Web Socket Protocol Handshake\r\n]
            [Message: HTTP/1.1 101 Web Socket Protocol Handshake\r\n]
            [Severity level: Chat]
            [Group: Sequence]
        Request Version: HTTP/1.1
        Status Code: 101
        Response Phrase: Web Socket Protocol Handshake
    Upgrade: WebSocket\r\n
    Connection: Upgrade\r\n
    Sec-WebSocket-Accept: xO65RkfOOMva29LmSc/tSQML7ak=\r\n
    Server: Kaazing Gateway\r\n
    Date: Sat, 13 Jul 2013 08:14:15 GMT\r\n
    Access-Control-Allow-Origin: http://www.websocket.org\r\n
    Access-Control-Allow-Credentials: true\r\n
    Access-Control-Allow-Headers: content-type\r\n
    Access-Control-Allow-Headers: authorization\r\n
    Access-Control-Allow-Headers: x-websocket-extensions\r\n
    Access-Control-Allow-Headers: x-websocket-version\r\n
    Access-Control-Allow-Headers: x-websocket-protocol\r\n
    \r\n
    [HTTP response 1/1]

Автор: Bulat 16.7.2013, 19:53
arto, делать мне больше нечего, как тебя учить.. Если ты не в состоянии увидеть свои ошибки сам.............

Автор: arto 16.7.2013, 21:03
учить не надо. просто указать на ошибки.

Автор: Bulat 16.7.2013, 21:19
Цитата(arto @  12.7.2013,  07:42 Найти цитируемый пост)
2. RFC 6455 1.2.  Protocol Overview: The handshake from the server looks as follows:

        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat


Цитата(arto @  13.7.2013,  11:43 Найти цитируемый пост)
пс. дамп хендшейка с http://www.websocket.org/echo.html:
Hypertext Transfer Protocol
    HTTP/1.1 101 Web Socket Protocol Handshake\r\n
        [Expert Info (Chat/Sequence): HTTP/1.1 101 Web Socket Protocol Handshake\r\n]
            [Message: HTTP/1.1 101 Web Socket Protocol Handshake\r\n]


Давай без обид... Но ты сейчас устроил небольшой флуд, пытаясь гнуть передо мной пальцы и демонстрируя ум, там где его нет.. Я даже не лезу в рфс, я просто процитирую тебя... Обрати внимание на строки

HTTP/1.1 101 Switching Protocols
HTTP/1.1 101 Web Socket Protocol Handshake\r\n

Автор: arto 16.7.2013, 21:32
RFC 2616 6.1.1 Status Code and Reason Phrase:

   The Status-Code element is a 3-digit integer result code of the
   attempt to understand and satisfy the request. These codes are fully
   defined in section 10. The Reason-Phrase is intended to give a short
   textual description of the Status-Code. The Status-Code is intended
   for use by automata and the Reason-Phrase is intended for the human
   user. The client is not required to examine or display the Reason-
   Phrase.

ещё есть замечания?

Автор: Bulat 16.7.2013, 22:50
arto, 

HTTP/1.1 101 Switching Protocols
HTTP/1.1 101 Web Socket Protocol Handshake\r\n

Разница в этих двух строках есть или полностью одинаковые??

Автор: arto 17.7.2013, 07:39
с точки зрения клиента -- одинаковые.
с тоэки зрения человека -- разные.

советую прочитать соответствующие rfc.

Автор: Bulat 17.7.2013, 17:22
arto, что в лоб, что по лбу  smile 

Я тогда задам вопрос по другому, рфс для кого пишут?? Для "клиентов" или для "людей"??

Автор: ginnie 17.7.2013, 17:46
Чтобы обсуждение не выглядело, как дуэль, тоже задам вопрос
Цитата(Bulat @  12.7.2013,  06:25 Найти цитируемый пост)
2. При формировании ответного ключа необходимо дополнять символом '=', и действительно в примерах так оно и укаано, а в описании я об этом ничего не нашел

Откуда Вы это правило взяли? У Вас в примере
Цитата(Bulat @  10.7.2013,  16:52 Найти цитируемый пост)
Sec-WebSocket-Accept: SL2qAawt3BX3DYVcQvXWOgB3DWE

значение состоит из 27 символов, т.е. оно не соответствует кодировке base64.

И еще вопросик: с каким из заголовков 
Код

HTTP/1.1 101 Switching Protocols
HTTP/1.1 101 Web Socket Protocol Handshake

не работает?

Автор: Bulat 18.7.2013, 04:18
Цитата(ginnie @  17.7.2013,  17:46 Найти цитируемый пост)
Откуда Вы это правило взяли? У Вас в примере

Методом проб и ошибок....

Если мне не веришь, попробуй сам протестируй.

Цитата(ginnie @  17.7.2013,  17:46 Найти цитируемый пост)
значение состоит из 27 символов, т.е. оно не соответствует кодировке base64.


Вот кодировке base64 оно как раз и соответствует.

Цитата(ginnie @  17.7.2013,  17:46 Найти цитируемый пост)
И еще вопросик: с каким из заголовков 


И с тем и с тем, работающий вариант,

либо
Код

HTTP/1.1 101 Switching Protocols\r\n


либо

Код

HTTP/1.1 101 Web Socket Protocol Handshake\r\n

Автор: Bulat 18.7.2013, 05:04
Кто умеет тот делает кто не умеет тот учит других.  Бернард Шоу

Автор: arto 18.7.2013, 07:38
т.е. вы не знаете, для кого пишутся rfc?
называется -- приехали, такие сейчас разработчики, хе-хе :)

Добавлено через 3 минуты и 52 секунды
btw, perldoc -m Protocol::WebSocket::Response
...
sub _parse_first_line {
    my ($self, $line) = @_;

    my $status = $self->status;
    unless ($line =~ m{^HTTP/1\.1 $status }) {
        $self->error('Wrong response line');
        return;
    }

    return $self;
}
...

Автор: ginnie 18.7.2013, 12:53
Цитата(Bulat @  18.7.2013,  04:18 Найти цитируемый пост)
Вот кодировке base64 оно как раз и соответствует.

Открываем rfc4648 (The Base16, Base32, and Base64 Data Encodings) и читаем
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters.  Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single character in the base 64
alphabet.
т.е. результат по длине всегда кратен 4 символам, а 27 никак 4 не кратно.

P.S. "Всякая профессия есть заговор против непосвященного." Бернард Шоу

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)