我认为传出消息的大小实际上不是问题。我有同样的问题,将“max_payload_size”设置为更大的值并不能解决它。如果这是问题所在,您会看到 Frame.pm "to_bytes" 子“有效负载太大。发送较短的消息或增加 max_payload_size”的错误消息。当我通过 16k 从服务器向 Chrome 发送消息时,我在服务器上看不到此错误(或任何其他错误),是的,我仍然收到“无法将文本帧解码为 UTF-8”和“(操作码 - 1)" 作为在 Chrome 检查器网络选项卡中以红色突出显示的框架消息正文。
我认为这更有可能是一个 IO::Socket::SSL 问题,因为我按照 Net::WebSocket::Server 文档中的规定使用它。我很好奇您是否还好,或者您是否在常规未加密的套接字中看到了这个问题。
来自 IO::Socket::SSL 文档:
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 字符串发送回 Chrome,该字符串以前无法通过 SSL 工作。