does your script end the connection after it receives gprs client data or keeps waiting for next data from client.
This loop in gprsClient() will (does on my system), continue to read and print anything that arrives from the gprs client until the client socket is close or an error occurs:
print "$unitId: Command response: $_" while <$client>;
Which should only happen (under normal circumstances) when the gprs client closes the connection.
Oshalla has pointed out that if the physical transport layer is disconnected, or if the client simply hangs, then that read will never return as coded. And that is the original problem you are trying to solve.
I think that the solution (hinted at above) is to use setsockopt with SO_RCVTIMEO, to effect an inactivity timer on reads. From a *nix manpage for setsckopt:
SO_RCVTIMEO is an option to set a timeout value for input operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for input operations to complete. In the current implementation, this timer is restarted each time additional data are received by the protocol, and thus the limit is in effect an inactivity timer. If a receive operation has been blocked for this much time without receiving additional data, it returns with a short count or with the error EWOULDBLOCK if no data were received. The struct timeval parameter must represent a positive time interval; otherwise, setsockopt() returns with the error EDOM.
This works perfectly on my system(*). With your clients sending regular data, the timeout gets reset to the value you supply each time something is received.
If you were to set a value of (say) 3x the frequency of that regular update, then if the client hangs, or the transport is cut for any reason, it will timeout the read whenever 3 updates have been missed. That would make for very simple client thread procs and a very reliable server.
My suggestion to you is to try this in your existing working code:
... if( $lclient->connected ){ ## I'm assuming that the setsockopt implementation on your sys +tem ## will build the appropriate struct timeval from 15.0 setsockopt( $client, SOL_SOCKET, SO_RCVTIMEO, 15.0 ) or $!; while( <$lclient> ) { ...
You might need to switch from readline (<$client>) to recv... which means you'd need to do your own buffering.
You should also note that your current code (despite is "working" status) contains a lot of very dubious code. Particularly with respect to no locking and sharing through cloning. That's why I tried to provide you with a simplified "equivalent", before trying to address the OP problem. Unfortunately, the differences between or two systems make trying to work out why my code doesn't work on your system rather difficult. I knew there would likely be some problems, but if you can't get it to work at all, there is no base to work from. (It runs very nicely here!).
When done from C! I haven't worked out the combination of magic required to do it from Perl yet :(
In reply to Re^7: Non closing sockets - threads
by BrowserUk
in thread Non closing sockets - threads
by igor1212
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |