2012-11-08 64 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()的组合来完成这个诀窍。 –