8

As I understand, it is possible to create a nonblocking network socket in PHP 5.x.

But what happens if a script sends several long messages using the same nonblocking socket as follow:

socket_write($socket, $string1, $length);
socket_write($socket, $string2, $length);
socket_write($socket, $string3, $length);
socket_write($socket, $string4, $length);

Are these messages queued (on the sender/receiver side?) or is it possible that the receiver gets parts of different messages because they sent "parallel"?

For example: Is is possible that the receiver gets 10 bytes of $string1, then 30 bytes of $string2, then another 25 bytes of $string1 ... and so on....

hakre
  • 193,403
  • 52
  • 435
  • 836
Mike
  • 1,992
  • 4
  • 31
  • 42

1 Answers1

6

It depends on the protocol that the socket is using. See socket_create for the possible types of sockets. The main types are UDP and TCP:

udp The User Datagram Protocol is a connectionless, unreliable, protocol with fixed record lengths. Due to these aspects, UDP requires a minimum amount of protocol overhead.

tcp The Transmission Control Protocol is a reliable, connection based, stream oriented, full duplex protocol. TCP guarantees that all data packets will be received in the order in which they were sent. If any packet is somehow lost during communication, TCP will automatically retransmit the packet until the destination host acknowledges that packet. For reliability and performance reasons, the TCP implementation itself decides the appropriate octet boundaries of the underlying datagram communication layer. Therefore, TCP applications must allow for the possibility of partial record transmission.

To answer your question directly, TCP sockets will guarantee in-order delivery, whereas UDP sockets will not.

Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
  • +1 Also see http://stackoverflow.com/questions/1432477/can-php-asynchronously-use-sockets – msanford Mar 16 '12 at 15:38
  • 2
    That means for my example above: TCP sockets will guarantee that the receiver will never see data from $string2, 3 or 4 until $string1 was received completely? – Mike Mar 16 '12 at 15:40
  • 2
    Yes, but keep in mind all data is written out to the same socket, so the receiver will see the data as a single stream of information. Unless you add string lengths, delimiters, or some other information to your data, the receiver will not know where `$string1` ends and `$string2` begins. – Justin Ethier Mar 16 '12 at 15:46
  • 1
    @Justin Ethier Thats the information I was looking for! :-) Thanks a lot. I've also updated my question with an example to clarify. – Mike Mar 16 '12 at 15:55
  • 3
    @Mike: Keep in mind that this is somewhat PHP-specific. If you start multithreading (something PHP does not support, but others, like C or Java do), you have to implement mutexes (locks) on your socket to prevent this kind of weird, unexpected behavior on the receiver side. – netcoder Mar 16 '12 at 16:05
  • 2
    @netcoder That's an important info because I will also create a c# socket app. That means, I have to lock a sending socket until the complete data has been sent? If so: why then not just using blocking sockets? – Mike Mar 16 '12 at 16:06
  • 1
    @Mike: If you multi-thread, a non-locked socket can potentially be accessed by two different threads at the same time, resulting in gibberish (10 bytes from thread A, then 10 bytes from thread B then 10 bytes from thread A again). Mutexes have nothing to do blocking sockets. Blocking sockets blocks (hangs) your application or thread until something happens (reception or sending of data, accepting a new connection, dropping an existing connection, etc.). Locking a socket with a mutex will prevent it from being manipulated by two threads at the same time. – netcoder Mar 16 '12 at 16:52
  • 1
    My comment about locking is only important if you *multi-thread* and plan to *share* socket resources across threads. – netcoder Mar 16 '12 at 16:56
  • @netcoder My C# does multi-thread and share socket resources across threads. Last question: I understand how to lock the socket, but how can I remove the lock? Should the socket fire an event when sending data is complete, which I can use to unlock the socket? – Mike Mar 16 '12 at 23:00
  • 1
    @Mike: Can't really help you there. I'm not very knowledgeable in C# (yet). Post some of your code in a new question, there are plenty of C# pros on SO. :) – netcoder Mar 17 '12 at 15:13