虽然Jirka Hanika给出的答案对于大多数系统都是正确的,但我得出的结论是遗憾地不适用于 PHP;使用 PHP套接字扩展重新使用套接字是不可能从用户空间实现的。
导致这个结论的代码是:
function statDescriptors() {
foreach (glob('/proc/self/fd/*') as $sFile) {
$r = realpath($sFile);
// ignore local file descriptors
if($r === false) {
echo `stat {$sFile}`, "\n";
}
}
}
header('Content-Type: text/plain');
statDescriptors();
$oSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($oSocket, SOL_SOCKET, SO_KEEPALIVE, 1);
socket_set_option($oSocket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_connect($oSocket, '173.194.35.33', 80); // Google IP
socket_write($oSocket, 'GET / HTTP/1.0' . "\r\n");
socket_write($oSocket, 'Connection: Keep-Alive' . "\r\n\r\n");
socket_read($oSocket, 1024 * 8);
// socket_close($oSocket); // toggle this line comment during test
echo 'PID is: ', getmypid(), "\n";
statDescriptors();
此代码将stat()
在当前进程的执行开始和结束时打开套接字文件描述符。在两者之间,它将打开一个带有SO_KEEPALIVE
set 的套接字,向其写入请求并读取响应。然后它会选择性地关闭套接字(切换行注释)并回显当前进程的 PID(以确保您在同一个进程中)。
您将看到,无论您是否关闭套接字,为上一个请求创建的文件描述符在此循环执行开始时将不再存在,并且将创建并连接一个全新的套接字。
我无法测试SOCK_CLOEXEC
,因为它(还没有?)在扩展中实现。
(这是使用 PHP 5.4.0 测试的)