Perl Websocket服务器在Chrome中导致“无法将文本框架解码为UTF-8”

时间:2014-12-17 00:03:30

标签: perl websocket

当使用Perl的Websocket server时,如果我使用长度大于16,000个字符的send_utf8发送json消息,则会导致与Chromeocket的连接在Chrome中被杀死并显示以下消息:

“无法将文本框架解码为UTF-8”。

此Websocket服务器可以发送的消息长度是否存在一些限制,是否有办法解决此限制?

3 个答案:

答案 0 :(得分:3)

它失败,因为(截至0.001003)Net :: WebSocket :: Server :: Connection初始化其Protocol :: WebSocket :: Frame对象而不设置" max_payload_size"它会覆盖65535字节的限制。如果模块作者更新这些调用以允许更大的缓冲区或更好的缓冲区来传递用户定义的值,则可以轻松解决该问题。

答案 1 :(得分:2)

显然,可以在Protocol :: WebSocket :: Frame构造函数(https://github.com/vti/protocol-websocket/issues/24#issuecomment-27095561)中设置有效负载大小。

不幸的是,cpan上的文档似乎缺少这些信息。

试试这个:

$hs->build_frame(buffer => $my_data, max_payload_size => 200000)->to_bytes);

答案 2 :(得分:-1)

我认为传出消息的大小实际上不是问题。我有同样的问题并设置" max_payload_size"更大的值并不能解决问题。如果这是问题,您将看到来自Frame.pm" to_bytes"的错误消息。 sub" Payload太大了。发送较短的消息或增加max_payload_size"。当我从服务器向Chrome发送超过16k的消息时,我没有在服务器上看到此错误(或任何其他错误),是的,我仍然得到"无法将文本框架解码为UTF-8"使用"(操作码-1)"在Chrome检查器网络标签中以红色突出显示框架邮件正文。

我认为这更像是一个IO :: Socket :: SSL问题,因为我在Net :: WebSocket :: Server文档中使用它作为规定。我很好奇,如果你很好,或者你在常规的未加密套接字中看到这个问题。

来自IO :: Socket :: SSL Docs:

  

syswrite(BUF,[LEN,[OFFSET]])此函数的行为来自   与其他IO :: Socket对象中的syswrite相同,例如它会   最多将LEN字节写入套接字,但不能保证   写入所有LEN字节。它将返回写入的字节数。   syswrite将在单个SSL帧中写入所有数据   意味着,不超过16,384字节,这是一个的最大大小   SSL帧,可以立即写入。

Net :: WebSocket :: Server :: Connection在构建框架后调用syswrite:

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

任何想法如何解决这个我很好奇。使用SSL时,Frame模块可能会将16k以下的消息分段,但是我认为这必须在Connection.pm中处理。

更新解决方案:

事实证明,如果您愿意修改Connection.pm并将syswrite放入16k循环中,这是一个非常简单的修复。记住SSL帧和WebSocket帧不是一回事,我们只需要不溢出SSL帧大小。见工作解决方案:

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: $@" if $@;
    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);
}

我能够将一个27k json字符串发送回以前没有通过SSL工作的Chrome。