Variable length packets in php

I receive packets sent to my server via UDP. I use socket_read to read data and it goes well. However, I ran into an error. The length parameter for socket_read is NOT always the same in my case. The data length can vary from 50 to 150 bytes. The only thing that remains constant is that the data set ends with byte \ x00. How could I read the read function, which is always read until it encounters this byte? I already tried the PHP_NORMAL_READ flag, but the docs say that it ends only in \ n or \ r, which is really not what I want (tried it, it does not work for my data). At the same time, the php page for socket_read states in the description of the length parameter that

The maximum number of bytes read specified by the length parameter. Otherwise, you can use \ r, \ n or \ 0 for (depending on the type of parameter, see below).

The type says nothing about the / 0 byte. It, as part of the documentation, is missing. I need a function that allows me to specify a separator for my data, it will automatically read all the data from an existing socket. There may be a solution in the socket_recv function, but it is undocumented, and I do not know how this works.

Thanks in advance.

+4
source share
4 answers

If I understand correctly, you want to read data from the socket until there is more data to read, while the problem is that the amount of data is variable, and you do not know when to stop.

According to the corresponding manual page ( http://php.net/socket_read ):

Note: socket_read () returns zero string length ("") when there is no more data to read.

You should be able to process variable-length data by reading byte bytes until you press a zero-length string:

while (($currentByte = socket_read($socket, 1)) != "") { // Do whatever you wish with the current byte } 
+4
source

A read payload application will need to know when you have reached the β€œend of recording” for any message sent to the application. Expect an arbitrary length when reading.

Use caution with UDP, as you cannot guarantee that the packet reading order is the order sent by the peer if you are trying to send multiple messages to a message. In this case, it is recommended to use a TCP socket.

0
source

Have you tried something like this:

 do { echo socket_read($handle,1024); $status = socket_get_status($handle); } while($status['unread_bytes']); 
0
source

I switched to another approach that can only work in your case:

 <?php function tftp_fetch($host, $filename) { $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // create the request packet $packet = chr(0) . chr(1) . $filename . chr(0) . 'octet' . chr(0); // UDP is connectionless, so we just send on it. socket_sendto($socket, $packet, strlen($packet), 0x100, $host, 69); $buffer = ''; $port = ''; $ret = ''; do { // $buffer and $port both come back with information for the ack // 516 = 4 bytes for the header + 512 bytes of data socket_recvfrom($socket, $buffer, 516, 0, $host, $port); // add the block number from the data packet to the ack packet $packet = chr(0) . chr(4) . substr($buffer, 2, 2); // send ack socket_sendto($socket, $packet, strlen($packet), 0, $host, $port); // append the data to the return variable // for large files this function should take a file handle as an arg $ret .= substr($buffer, 4); } while(strlen($buffer) == 516); // the first non-full packet is the last. return $ret; } ?> 

The most interesting part of this approach:

 do ... while(strlen($buffer) == 516); // the first non-full packet is the last. 
0
source

All Articles