2014-12-17 14 views
5

Khi sử dụng số Websocket server của Perl, nếu tôi gửi một tin nhắn json bằng send_utf8 dài hơn khoảng 16.000 ký tự, nó sẽ khiến kết nối tới websocket bị giết trong Chrome với thông báo:Máy chủ Websocket Perl gây ra "không thể giải mã khung văn bản dưới dạng UTF-8" trong Chrome

"Không thể giải mã khung văn bản dưới dạng UTF-8".

Có một số hạn chế về độ dài của tin nhắn có thể được gửi bởi máy chủ Websocket này không và có cách nào để khắc phục hạn chế này không?

+0

Tôi gửi qua email tác giả của thư viện và viết: "Giới hạn áp đặt bởi Giao thức cơ bản :: WebSocket :: Mô-đun khung có vẻ là 65535 byte". Tôi nghĩ rằng điều này là có liên quan và giới hạn ký tự ~ 16.000 mà tôi đánh có thể là do send_utf8 xử lý mỗi ký tự là 4 byte. Tôi hy vọng cho một câu trả lời rõ ràng hơn mặc dù, và một workaround có thể. –

Trả lời

3

Không thành công vì (tính đến 0.001003) Net :: WebSocket :: Server :: Kết nối khởi tạo giao thức :: WebSocket :: Khung đối tượng mà không đặt "max_payload_size" ghi đè giới hạn byte 65535. Vấn đề có thể dễ dàng được giải quyết nếu tác giả mô-đun cập nhật các cuộc gọi đó để cho phép bộ đệm lớn hơn, hoặc tốt hơn, để vượt qua giá trị do người dùng xác định.

-1

Tôi nghĩ rằng kích thước của thông điệp gửi đi là trong thực tế không phải là vấn đề. Tôi có cùng một vấn đề chính xác và đặt "max_payload_size" thành giá trị lớn hơn không giải quyết được. Nếu đây là vấn đề bạn sẽ thấy thông báo lỗi từ Frame.pm "to_bytes" sub "Tải trọng quá lớn. Gửi tin nhắn ngắn hơn hoặc tăng max_payload_size". Khi tôi gửi tin nhắn từ máy chủ đến Chrome trên 16k, tôi không thấy lỗi này (hoặc bất kỳ lỗi nào khác) trên máy chủ, vâng tôi vẫn nhận được "Không thể giải mã khung văn bản thành UTF-8" bằng "Mã hóa - 1) "làm cơ thể thông báo khung được đánh dấu bằng màu đỏ trong tab mạng thanh tra của Chrome.

Tôi nghĩ rằng nhiều khả năng đây là vấn đề IO :: Socket :: SSL, vì tôi đang sử dụng nó như được quy định trong tài liệu Net :: WebSocket :: Server. Tôi tò mò nếu bạn là tốt, hoặc nếu bạn thấy vấn đề này trong ổ cắm un-uncrypted thường xuyên.

Từ IO :: Ổ cắm :: SSL Documents:

syswrite (BUF, [LEN, [OFFSET]]) chức năng này hoạt động từ bên ngoài giống như syswrite trong IO khác :: Ổ cắm đối tượng, ví dụ nó sẽ ghi tối đa LEN byte vào ổ cắm, nhưng không có bảo đảm, rằng tất cả các byte LEN được viết. Nó sẽ trả về số byte được ghi. syswrite sẽ ghi tất cả dữ liệu trong một khung SSL, trong đó có nghĩa là không quá 16,384 byte, kích thước tối đa là khung SSL , có thể được viết cùng một lúc.

Net :: WebSocket :: Máy chủ :: Kết nối được gọi syswrite sau khung được xây dựng:

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

Bất kỳ ý tưởng làm thế nào để đối phó với điều này Tôi tò mò về. Có lẽ mô-đun Khung nên phân mảnh các thông báo dưới 16k khi sử dụng SSL, nhưng điều đó sẽ phải được xử lý trong Connection.pm tôi nghĩ.

CẬP NHẬT với giải pháp:

nó quay ra đây là một sửa chữa khá dễ dàng nếu bạn sẵn sàng để thay đổi Connection.pm và đặt syswrite vào một vòng lặp 16k. Nhớ rằng khung SSL và khung WebSocket không giống nhau, chúng ta chỉ cần không làm tràn kích thước khung SSL. Xem giải pháp làm việc:

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); 
} 

Tôi đã có thể gửi một chuỗi jk 27k trở lại Chrome trước đó không hoạt động qua SSL.

Các vấn đề liên quan