2017-01-21 5 views
0

У меня есть следующий код для получения данных с помощью websocket.PHP Websocket, получающий неполные данные

$bytes=socket_recv($socket,$buffer2,1024,0); 
$datarec=unmask($buffer2); 
//process further 

Это работает, но много раз я получаю неполные сообщения, и я не могу обработать данные дальше.

У меня появилось следующее решение.

В основном я резервирую первые 10 цифр для длины данных и перед отправкой их с помощью socket.send из javascript. Я добавляю длину данных в начале сообщения. Поэтому, если мое сообщение «привет, это сообщение», оно становится «30: sizehello это сообщение« Я компенсирую добавленный «30: размер».

На стороне PHP я надеюсь сделать это

Сначала прочитайте 10 цифр.

$length=socket_recv($socket,$buffer2,1024,MSG_WAITALL); 

, а затем использовать что-то вроде

$datarec=aocket_recv($socket,$buffer2,$length,MSG_WAITALL); 

К сожалению, это не работает, как я не могу читать и разоблачить данные, полученные с socket_recv 2-й раз.

Любые предложения о том, как получить полные данные из websocket, не зная длины данных перед началом работы. Спасибо за вашу помощь.

+0

Sockets = WebSockets –

+0

Благодаря код ошибки 0, но я полагал, что я не получаю неполных данных но данные фрагментированы. Теперь я действительно зациклился на том, как разоблачить фрагментированные данные. Я могу получить первый снимок, но не смог замаскировать следующий кадр. – user2288650

ответ

0

Решение этой проблемы заключается в следующем

Выпуск: При получении длинных байт данных с помощью WebSocket с чем-то вроде socket_recv($socket,$buffer,5000,0); вы не можете получить полные данные в одном вызове и вам нужно вызвать socket_recv($socket,$buffer,5000,0); снова.

Например, предположим, что мы отправили 8000 байт данных из браузера в websocket с помощью JS (socket.send). На стороне сервера мы будем использовать socket_recv для получения сообщения. Но мы можем получить только около 4000 байт данных и, возможно, придется снова вызвать socket_recv, чтобы получить оставшиеся 4000 байт.

Теперь в моем исходном коде я использовал функцию «unmask» сразу после вызова socket_recv, чтобы разобрать данные. Это будет работать для первого набора полученных сообщений. Но для следующего набора сообщений функция «unmask» попытается извлечь новую маску и применить ее. Это была ошибка, так как сообщение является продолжением предыдущего сообщения, а Mask не изменяется. Решение состоит в том, чтобы сохранить маску от первого сообщения и проверить, является ли следующее сообщение продолжением или нет. Это можно сделать, проверив первый бит сообщения.

$fin=ord($payload[0]) & 0x77; 

если $ fin - это сообщение, это новое сообщение, если оно не является продолжением предыдущего сообщения. В случае ($ fin! = 1) вам нужно использовать маску вашего предыдущего сообщения, чтобы разоблачить сообщение. Не забывайте, так как вам нужно снова использовать значение маски, вам нужно определить его вне функции и сделать его глобальным.

Я предоставил старый и новый код ниже для справки. Надеюсь, это правильное решение, но, пожалуйста, не стесняйтесь добавлять что-либо или сообщать мне, если я ошибаюсь.

Мой Оригинальная функция Унмаск:

function unmask($payload) { 
    $length = ord($payload[1]) & 127; 
    if($length == 126) { 
     $masks = substr($payload, 4, 4); 
     $data = substr($payload, 8); 
     $firstcode=substr($payload, 1, 1); 
    } 


    elseif($length == 127) { 
     $masks = substr($payload, 10, 4); 
     $data = substr($payload, 14); 
     $firstcode=substr($payload, 1, 1); 

     } 
    else { 
     $masks = substr($payload, 2, 4); 
     $data = substr($payload, 6); 
     $firstcode=substr($payload, 1, 1); 

    } 
    $text = ''; 
for ($i = 0; $i < strlen($data); ++$i) { 
     $text .= $data[$i]^$masks[$i%4]; 
    } 

    return $text; 
} 

Обновлено Функция:

function unmask($payload,$masks) { 
global $masks; 
$fin=ord($payload[0]) & 0x77; 

if($fin!=1){  
    $data=substr($payload,0); 
    $text=''; 
    for ($i = 0; $i < strlen($data); ++$i) { 
     $text .= $data[$i]^$masks[$i%4]; 
    } 
    return $text; 
}else{ 
    $length = ord($payload[1]) & 127; 

    Echo "Mask functiion Payload Lenght".$length."\n"; 


    if($length == 126) { 
     $masks = substr($payload, 4, 4); 
     $data = substr($payload, 8); 
    } 


    elseif($length == 127) { 
     $masks = substr($payload, 10, 4); 
     $data = substr($payload, 14); 

     } 
    else { 
     $masks = substr($payload, 2, 4); 
     $data = substr($payload, 6); 

    } 
    $text = ''; 
for ($i = 0; $i < strlen($data); ++$i) { 
     $text .= $data[$i]^$masks[$i%4]; 
    } 
    return $text; 
} 

}