20

Typical PHP socket functionality is synchronous, and halts the thread when waiting for incoming connections and data. (eg. socket_read and socket_listen)

How do I do the same asynchronously? so I can respond to data in a data received event, instead of polling for data, etc.

Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607

4 Answers4

18

Yup, that's what socket_set_nonblock() is for. Your socket interaction code will need to be written differently, taking into account the special meanings that error codes 11, EWOULDBLOCK, and 115, EINPROGRESS, assume.

Here's some somewhat-fictionalized sample code from a PHP sync socket polling loop, as requested:

$buf = '';
$done = false;
do {
    $chunk = socket_read($sock, 4096);
    if($chunk === false) {
        $error = socket_last_error($sock);
        if($error != 11 && $error != 115) {
            my_error_handler(socket_strerror($error), $error);
            $done = true;
        }
        break;
    } elseif($chunk == '') {
        $done = true;
        break;
    } else { 
        $buf .= $chunk;
    }
} while(true);
chaos
  • 122,029
  • 33
  • 303
  • 309
  • What do you mean by differently? Can you show me any code samples of asynchronous data received events? – Robin Rodricks Sep 16 '09 at 12:06
  • 1
    So this is synchronous, but non-blocking? Then what exactly does non-blocking mean? – Robin Rodricks Sep 16 '09 at 17:54
  • 3
    No, it is asynchronous, and polling-based. The code is from a larger polling mechanism. PHP has no support for interrupt/signal driven socket I/O events like you're asking for, as far as I know. You achieve async communications by using operations that do not wait for completion but return immediately, with an indicative error code, if the operation isn't ready. Like reads on a non-blocking socket. There are lots of tutorials on async socket use in C that will go into lots of detail abou this; PHP's support is just a layer over the standard C stuff. – chaos Sep 16 '09 at 18:02
  • Its Aug/2012. Do you think the approach is updated/improved in the way OP wanted it? – Shiplu Mokaddim Aug 01 '12 at 15:55
  • can someone post example code for infitinty non blocking receiving data? please? – consigliere Jul 23 '15 at 00:33
  • THIS IS NOT ASYNC - it's non-blocking. It's cool - seriously - and a start to a perfect non-blocking solution, but it is not asynchronous. – JSON Sep 08 '18 at 04:15
  • Asynchronous doesn't mean concurrent. Concurrent means concurrent. The answer below this one and the comment above this one are nonsense. – chaos Sep 10 '18 at 15:14
  • @chaos see https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean . On any modern system this equates to concurrent processing (comes down to how the concept of a "thread" has changed over the last 2+ decades). Regardless of how you define "thread", setting a socket to non-blocking doesn't mean the network call will take place in a different time slice as the original calling thread. It just means the calling thread will not block due to I/O. Consequentially, dispatching a blocking call to a different thread will still allow async processing. – JSON Sep 23 '18 at 22:58
  • A non-blocking I/O call *will* ultimately prevent additional instructions from executing once it is able to do it's job making it in fact synchronous. This may seem like a stretch but any modern processor runs at time increments in the billionths of second (or less). Even a millionth of a sec represents a substantial amount of time on this scale, and non-blocking I/O will still delay further execution as long as it can operate. It's single thread nature means your only operating on one socket at a time so it's still synchronous on the network level too, albeit better shared between sockets. – JSON Sep 24 '18 at 05:56
4

How do I do the same asynchronously? so I can respond to data in a data received event, instead of polling for data, etc.

You will need to execute your script and issue stream_select to check weither there is any data to receive. Process and send data back.

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
  • stream_select has little to do with the ops question. The stream (ie the underlying socket) will need to be set to non-blocking and appropriate buffers will need to be kept (what if only 192 bytes of 1,456 are received before a blocking event.. if those 192 bytes are not buffered to continue on next read they are lost). Even then it's not async, just non-blocking. – JSON Sep 08 '18 at 04:09
4

The term "asynchronous" is often misused in network programming. For I/O, asynchronous is often just used as another word for non-blocking. This means that the process is able to continue before a call on the network api has completed transmission.

For process execution in general, asynchronous means that multiple instructions are able to be computed at once (concurrently.)

In other words, asynchronous I/O is not truly asynchronous unless multiple threads are used to allow multiple reads/write/accepts to occur concurrently - all sockets will sill have to wait on a synchronous non-blocking call if it has data to be read/written or will otherwise not block, and reading/writing a large file can still take seconds or even minutes if not interrupted. Note that this would require a perfect flow between the client and server or TCP itself will interrupt the transmission. For example, a server sending faster than a client can download would cause a block on a write.

So from a strict point of view PHP is not able to perform asynchronous networking, only non-blocking. In short, the progression of the process will stop while the network call is able to usefully read/write etc. However, the process will then continue when the call is not able to usefully read/write or would otherwise block. In a truly asynchronous system the process will continue regardless, and the read/write will be done in a different thread. Note that blocking I/O can still be done asynchronously if done in a different thread.

Moreover, PHP is not able to do event driven I/O without installing an extension that supports it. You will otherwise need to do some form of polling in order to do non-blocking I/O in PHP. The code from Chaos would be a functional non-blocking read example if it used socket_select.

With that said, the select function will still allow true non-blocking behavior in PHP. In C, polling services have a performance loss over event driven, so I'm sure that it would be the same for PHP. But this loss is in the nanoseconds-microseconds depending on the amount of sockets, where the time saved from a non-blocking call is typically milliseconds, or even seconds if the call is made to wait.

JSON
  • 1,819
  • 20
  • 27
-1

AFAIK PHP is strictly singlethreaded, which means you can't do this asynchronously, because Script execution is always linear.

It's been a while since i have done this, but as far as i recall, you can only open the socket, and have the script continue execution upon receiving data.

MGriesbach
  • 344
  • 2
  • 6
  • 1
    PHP provides stream_select for async socket operations, analogous to posix select(). – karunski Sep 16 '09 at 12:42
  • 1
    select() is synchronous: it just lets you know whether a socket is ready for reading/writing. You still call it from a single thread, and block on the select() call instead of the read() or write(). – Matt Connolly Nov 13 '12 at 02:32