2012-11-08 101 views
3

我有一個PHP客戶端通過純文本的Unix域套接字連接到本地C服務器程序。不過,我可以得到它關閉很好的唯一途徑是,如果我完成插口會議有:PHP如何才能正常關閉本地套接字連接...?

stream_socket_shutdown($sock, 1); // shutdown socket writing 
usleep(500 * 1000);   // wait for 0.5 seconds 
fclose($sock);    // actually close the socket (finally) 

我想優雅地關閉它就像我的C客戶端: -

shutdown(connection_fd, SHUT_WR);  // tell server we've stopped sending queries 
// Read from the socket until poll(connection_fd) yields POLLRDHUP/POLLHUP/POLLERR/POLLNVAL 
shutdown(connection_fd, SHUT_RDWR); // tell connection we've stopped listening 
close(connection_fd);     // close the whole connection (finally) 

但是,PHP似乎沒有直接的套接字poll()等效。我怎樣才能讓PHP優雅地關閉本地套接字?

回答

4

您試過stream_set_blocking()?如果設置了流是非阻塞的,你應該能夠關閉連接之前以消耗所有的未決數據的:

socket_shutdown($sock, STREAM_SHUT_WR); 
stream_set_blocking($sock, 0); 
while(fgets($sock) !== false) { ; } 
fclose($sock); 

編輯:使用的常數,並固定在一組阻擋命令使用正確的價值。

說明:通過將流設置爲非阻塞狀態,然後讀取所有內容,我們將使用輸入緩衝區中的所有數據。這大大加快了關機過程,通過發信號通知對方我們的緩衝器清晰,並且他可以給我們發送更多消息(如FIN數據包)。

它仍然有可能得到一個緩慢的關機,但不太可能。

+0

啊哈 - 你99%是正確的。如果將第一行更改爲'socket_shutdown($ sock,0);' (這就是你的意思:-)),那麼它確實似乎優雅地關閉了單個連接。但是,我不確定在多個連接處於活動狀態時這是否會按預期工作 - 我並不想讓我的PHP在等待。所以也許這不是完整的答案......你同意嗎? –

+0

由於套接字處於非阻塞模式,它實際上不會進行等待。相反會發生什麼,所有待處理的數據將被讀取而無需等待另一端發送更多的數據,這幾乎可以加快關閉操作的速度。 – slashingweapon

+0

我完全同意所有已發送的數據都會到達。但是,如果爲了響應服務器必須從(例如)附加的I2C設備獲取一些數據,則在發送查詢的客戶端和服務器響應之間可能存在顯着的延遲。我猜測,在那些(頻繁)情況下,PHP會旋轉等待,如果可能,我寧願避免。我猜測我最終會建立一個非阻塞fgets()調用和usleep()的組合來完成這個訣竅。 –