2012-03-16 2 views
4

Я хочу отправить сообщения JSON из скрипта PHP в приложение C# через сетевое соединение, используя PHP Sockets.Отправка данных сокетов с использованием значения ведущей длины

Usually, for binary protocols, первые 4 байта каждого сообщения должны быть целым числом, которое представляет длину (сколько байтов) сообщения.

В C# префикс каждое сообщение с целым числом, который указывает длину сообщения следующим образом:

byte[] msgBytes = UTF8Encoding.UTF8.GetBytes("A JSON msg");    
byte[] prefixBytes = BitConverter.GetBytes(msgBytes.Length); 
byte[] msgToSend = new byte[prefixBytes.Length + msgBytes.Length]; 
Buffer.BlockCopy(prefixBytes, 0, msgToSend, 0, prefixBytes.Length); 
Buffer.BlockCopy(msgBytes, 0, msgToSend, prefixBytes.Length, msgBytes.Length); 

Как я понимаю, в PHP функция socket_send только принимает строки. Итак, как я могу сделать то же префикс в PHP 5.x?

Обновление: Я отправил follow-up question о том, как обрабатывать такие префиксные данные при их получении из сетевого сокета.

ответ

5

В PHP строки являются двоичными.

Таким образом, вам необходимо закодировать значение целочисленной длины как двоичное представление целочисленного знака n un в виде строки с 4 символами (4 октета, 32 бита). См pack:

# choose the right format according to your byte-order needs: 

l signed long (always 32 bit, machine byte order) 
L unsigned long (always 32 bit, machine byte order) 
N unsigned long (always 32 bit, big endian byte order) 
V unsigned long (always 32 bit, little endian byte order) 

$string = pack('l', $length); 
5

Я думаю, вы могли бы использовать pack() преобразовать число байтов в двоичную строку. Когда вы отправляете свои данные по сети, вам, вероятно, нужно преобразовать, используя формат «N» (беззнаковый длинный, всегда 32-разрядный, большой порядковый байтовый порядок).

Вот пример:

$s="Hello World"; 
$length=pack("N",strlen($s)); 
socket_send($sock,$length.$s,4+strlen($s)); 
+2

Почему вы используете "N" (большой байтов порядка байтов)? – Mike

+2

@Mike: Пожалуйста, обратитесь к вашей документации по продукту .Net, тип которой применим здесь. Вероятно, 32-битное целое число со знаком, конечный результат зависит от вашего компьютера. Также проверьте спецификацию используемого протокола. Таким образом, 'L',' N' и 'V', вероятно, будут неправильными (даже если бы они были в моем ответе, вам нужно дважды проверить это со спецификациями, которые вы используете). – hakre

+2

@hakre благодарит за вашу помощь. Кажется, что приложение C# использует little-endian, поэтому «V» должен быть лучшим вариантом, не так ли? – Mike