Piszę w PHP prosty serwer działający po socketach. Schemat działania jest prosty:
1) klient wysyła ciąg znaków z komendą,
2) serwer odbiera ciąg,
3) serwer "myśli" przez kilkanaście-kilkadziesiąt sekund,
4) serwer wysyła odpowiedź,
5) klient odbiera odpowiedź i zamyka połączenie.
Sęk w tym, że mielenie w punkcie trzecim może trwać dowolnie długo i klient może w międzyczasie zamknąć połączenie, a odpowiedź zostanie wysłana na zamknięty port. Zgodnie z manualem funkcja socket_write() powinna zwrócić false w przypadku, gdy nie doszło do zapisania. Niestety, nigdy nie zwraca false, nawet jeśli klient w międzyczasie przerwie połączenie.
Wymyśliłem obejście z funkcją socket_shutdown, ale to wymusza schemat: jedno połączenie, jedno zapytanie, jedna odpowiedź. Może ktoś ma pomysł co z tym fantem zrobić?
#!/usr/bin/php -q <?php $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1); socket_bind($sock, '12.34.56.789', 10000); socket_listen($sock); while (true) { $read = $clients; if (socket_select($read, $write = null, $except = null, 0) < 1) continue; { $clients[] = $newsock = socket_accept($sock); socket_getpeername($newsock, $ip); } foreach ($read as $j => $read_sock) { $data = @socket_read($read_sock, 1024, PHP_NORMAL_READ); if ($data === false) { continue; } { // i tutaj pojawia się problem, bo socket_write nie zwraca błędu nawet jeśli połączenie zostanie przerwane if (@socket_write($read_sock, $data."\n") !== false) { // działa natomiast ręczne zamknięcie socketa, ale też nie zawsze (NAT). if (@socket_shutdown($read_sock) !== false) { } else { } } else { } } } } socket_close($sock); ?>