DWilliams Posted December 23, 2011 Share Posted December 23, 2011 Say I have a server written in PHP (don't ask ). Let's say I have 10 users connected to my script and one of those users, for the sake of the example, needs 10MB of data sent to them. If I send that data via socket_write(), does my program execution stop (therefor locking up every other user) until the data has gone through, or is the actual task of sending data over the tubes passed on to some lower level OS function so my program can get on with its flow? Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/ Share on other sites More sharing options...
trq Posted December 23, 2011 Share Posted December 23, 2011 What sort of server? In general, the server will lock unless it is written to accept multiple connections/requests. Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1300788 Share on other sites More sharing options...
DWilliams Posted December 23, 2011 Author Share Posted December 23, 2011 What sort of server? In general, the server will lock unless it is written to accept multiple connections/requests. A "simple" multiplayer game server using php/web sockets as the server and JS as the client. My 10MB example was a bit on the large side, nothing that large will likely ever be sent by the server, but still, if the server is locked while sending data then it will become locked up more the more users are connected, especially if their connections are bad. Might you have a link to something that explains how to better engineer a server? Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1300796 Share on other sites More sharing options...
trq Posted December 23, 2011 Share Posted December 23, 2011 I meant what protocol is the server? Web sockets are implemented using HTTP. Sorry, I don't really collect links but you should be able to find something on Google. You would probably be better implementing this in a language more specific to the task though. JavaScripts Node.js comes to mind, it's perfect for such things. Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1300803 Share on other sites More sharing options...
kicken Posted December 23, 2011 Share Posted December 23, 2011 If I send that data via socket_write(), does my program execution stop (therefor locking up every other user) until the data has gone through, or is the actual task of sending data over the tubes passed on to some lower level OS function so my program can get on with its flow? Sockets can operate in two different modes: 1) Blocking (default) 2) Non-blocking If in blocking mode, then yes, execution will stop until all the data is sent, and all your other clients will be left waiting. If in non-blocking mode, the function will send what it can then return. However, the OS does not keep the unsent data and slowly send it as it is able. This is something you have to manage yourself. socket_write returns the number of bytes successfully sent. If that is less than what you attempted to send, you need to store the excess bytes somewhere and try again later. Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1300900 Share on other sites More sharing options...
DWilliams Posted December 24, 2011 Author Share Posted December 24, 2011 If I send that data via socket_write(), does my program execution stop (therefor locking up every other user) until the data has gone through, or is the actual task of sending data over the tubes passed on to some lower level OS function so my program can get on with its flow? Sockets can operate in two different modes: 1) Blocking (default) 2) Non-blocking If in blocking mode, then yes, execution will stop until all the data is sent, and all your other clients will be left waiting. If in non-blocking mode, the function will send what it can then return. However, the OS does not keep the unsent data and slowly send it as it is able. This is something you have to manage yourself. socket_write returns the number of bytes successfully sent. If that is less than what you attempted to send, you need to store the excess bytes somewhere and try again later. Hmm, I'd previously been just calling socket_write and assuming magical network fairies took care of everything from that point on and carried my data from server to client. I'm a bit confused as to how TCP comes into effect here, though. I know that TCP is supposed to ensure that my packets arrive at their destination all intact and orderly, but if I send a chunk of data with socket_write over my TCP socket and it doesn't all get to the other side, isn't that contrary to TCP's guarantees or am I thinking about this on the wrong level? Given this knowledge, allow me to think out loud (and probably incorrectly) for how this should be done properly: I call socket_set_nonblock() on a user's socket as soon as they connect. Instead of having a send method that simply passes data on through socket_write, I should have it add data to a buffer. I should have some other code somewhere (where?) that routinely checks buffers and writes what it can, subtracting what went through until all data is sent. I don't know if I'm massively overthinking this of massively underthinking it I'm beginning to think all of this cannot be accomplished in a timely manner with only one thread? Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1301024 Share on other sites More sharing options...
kicken Posted December 24, 2011 Share Posted December 24, 2011 I'm a bit confused as to how TCP comes into effect here, though. I know that TCP is supposed to ensure that my packets arrive at their destination all intact and orderly, but if I send a chunk of data with socket_write over my TCP socket and it doesn't all get to the other side, isn't that contrary to TCP's guarantees or am I thinking about this on the wrong level? TCP guarantees that the packets arrive intact and in order, yes. TCP doesn't take over until the OS's networking stack actually accepts the data. sockets have both a receive and a send buffer. If either of these buffers is full, the OS will reject any new data. So if an application is not reading the data and the read buffer fills up, then the OS will stop accepting new packets (and will tell the remote server this so it stops transmitting). This will cause the remote OS's write buffer to fill up. The write buffer could also fill up if a network condition is preventing packets from being delivered, or they are being delivered too slowly. Once full, the remote OS will stop accepting data for writing. The blocking mode determines what actually happens in the event these buffers are full. If you have blocking enabled, your read/write calls will block execution until the request can be satisfied. For reading that means until enough data is received, and for writing that is until all the given data can be successfully sent (or in either case until an error occurs). In non-blocking mode the read/write calls will give up, and return control back to you. Their return values indicate how much data was successfully read/written so you can take action accordingly. I call socket_set_nonblock() on a user's socket as soon as they connect. Instead of having a send method that simply passes data on through socket_write, I should have it add data to a buffer. I should have some other code somewhere (where?) that routinely checks buffers and writes what it can, subtracting what went through until all data is sent. Yes, that is pretty much correct. You will want a separate application buffer for reading and writing data. You'll also have to code your application with the understanding that a read or a write may not complete all at once. For instance, if your reading a packet off the wire, you need to be able to "abort" that read and try again later if the packet is not complete because the data has not all come through yet. The way I handle this typically is by reading data into the read buffer, then using some parsing techniques to run through the buffer til I have a full packet. If I get a full one, I chop the buffer at that point, otherwise it is left intact until the read is tried again. I don't know if I'm massively overthinking this of massively underthinking it I'm beginning to think all of this cannot be accomplished in a timely manner with only one thread? socket_select() is the key to everything. it will inform you when a socket is ready to be read from or written to. Your application should be centered around a loop on the socket_select call. Something like: do { $r=/* add sockets */ $w=/* add sockets */ $e=null; $n = socket_select($r, $w, $e, null, null); if ($n > 0){ foreach ($w as $s){ ///write these sockets } foreach ($r as $s){ //read these sockets } } } while (/* you have sockets available */); Quote Link to comment https://forums.phpfreaks.com/topic/253736-does-socket_write-block-until-all-data-is-sent/#findComment-1301076 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.