2014-12-17 7 views
5

Quando si utilizza Perl Websocket server, se si invia un messaggio json utilizzando send_utf8 che è più lungo di circa 16.000 caratteri, provoca la connessione al websocket ucciso in Chrome con il messaggio:Perl Websocket Server che causa "impossibile decodificare una cornice di testo come UTF-8" in Chrome

"Impossibile decodificare una cornice di testo come UTF-8".

C'è qualche restrizione sulla lunghezza dei messaggi che possono essere inviati da questo server Websocket e c'è un modo per aggirare questa restrizione?

+0

Ho inviato un'email all'autore della libreria e ha scritto: "Il limite imposto dal protocollo Protocol :: WebSocket :: Frame sottostante sembra essere 65535 byte". Penso che questo sia correlato e il limite di ~ 16.000 caratteri che sto colpendo potrebbe essere dovuto al fatto che send_utf8 considera ogni carattere come 4 byte. Spero comunque una risposta più precisa e una possibile soluzione alternativa. –

risposta

3

Non riesce perché (a partire da 0.001003) Net :: WebSocket :: Server :: Connection inizializza i relativi oggetti Protocol :: WebSocket :: Frame senza impostare "max_payload_size" che sovrascrive il limite di 65535 byte. Il problema può essere facilmente risolto se l'autore del modulo aggiorna tali chiamate per consentire buffer più grandi, o meglio, per passare attraverso un valore definito dall'utente.

-1

Penso che la dimensione del messaggio in uscita in realtà non è il problema. Ho lo stesso identico problema e impostare "max_payload_size" su un valore più grande non lo risolve. Se questo fosse il problema, vedresti il ​​messaggio di errore da Frame.pm "to_bytes" sub "Il payload è troppo grande, invia messaggi più brevi o aumenta max_payload_size". Quando invio un messaggio dal server a Chrome su 16k non vedo questo errore (o qualsiasi altro) sul server, sì, ho ancora il messaggio "Impossibile decodificare una cornice di testo come UTF-8" con un "(Opcode - 1) "come il corpo del messaggio frame evidenziato in rosso nella scheda Rete dell'ispettore Chrome.

Penso che sia molto più probabile che si tratti di un problema IO :: Socket :: SSL, poiché lo sto utilizzando come prescritto nei documenti di Net :: WebSocket :: Server. Sono curioso di sapere se stai bene o se vedi questo problema in normali prese non crittografate.

Dal IO :: Socket :: SSL Documenti:

syswrite (BUF, [LEN, [Offset]]) Questa funzione si comporta da al di fuori della stessa syswrite in altri IO :: Socket oggetti, ad es sarà scrivere nella maggior parte dei byte LEN al socket, ma non è garantito che sia scritto tutti i byte LEN. Restituirà il numero di byte scritti. syswrite scriverà tutti i dati all'interno di un singolo frame SSL, che significa , che non può essere scritto più di 16.384 byte, che è la dimensione massima di un frame SSL in una sola volta.

Net :: WebSocket :: Server :: Connection sta chiamando syswrite dopo che il telaio è costruito:

syswrite($self->{socket}, $bytes); 

Delle idee come affrontare questo mi incuriosisce. Forse il modulo Frame dovrebbe frammentare i messaggi sotto 16k quando si utilizza SSL, ma questo dovrebbe essere gestito in Connection.pm, penserei.

AGGIORNATO con la soluzione:

si scopre questo è una correzione abbastanza facile se si è disposti a modificare il Connection.pm e mettere lo syswrite in un ciclo 16k. Ricordando che i frame SSL e i frame WebSocket non sono la stessa cosa, non è necessario che la dimensione del frame SSL sia eccessiva. Vedere soluzione di lavoro:

sub send { 
    my ($self, $type, $data) = @_; 

    if ($self->{handshake}) { 
    carp "tried to send data before finishing handshake"; 
    return 0; 
    } 

    my $frame = new Protocol::WebSocket::Frame(type => $type, max_payload_size => $self->{max_send_size}); 
    $frame->append($data) if defined $data; 

    my $bytes = eval { $frame->to_bytes }; 
    if (!defined $bytes) { 
    carp "error while building message: [email protected]" if [email protected]; 
    return; 
    } 

    # modified to not overflow the 16k SSL frame size 
    while(16384 < length $bytes) { 
    syswrite($self->{socket}, $bytes, 16384); 
    substr($bytes, 0, 16384, ''); 
    } 
    syswrite($self->{socket}, $bytes); 
} 

Sono stato in grado di inviare una stringa json 27k a Chrome che non aveva precedentemente funzionato su SSL.

Problemi correlati