编辑: *测试工具中的错误导致我误解了结果。完全socket_select()
按照您的预期工作:它确实会等到套接字上准备好数据。但是如果您在客户端关闭连接后调用它,它将报告就绪。原来这都是我的错,但我会把问题留在这里,以防其他人怀疑.socket_select()
我有一个多线程 PHP 应用程序,我正在使用套接字在线程之间进行通信。通信工作得很好,但我最终对没有准备好数据的套接字进行了很多不必要的读取。也许我缺少一些关于套接字编程的东西。
PHP 文档socket_select()
说将观察数组中列出的套接字read
以查看读取是否不会阻塞。
这正是我想要的行为:打电话socket_select()
等到我的一个子线程试图与我交谈。但这仅适用于线程第一次写入,在我接受连接之后。之后,socket_select()
将永远说套接字已准备就绪,即使我已经从中读取了所有数据。
有什么方法可以将该套接字标记为“未就绪”,以便socket_select()
在更多数据到达之前不会报告它已准备好?还是在我读取所有数据后关闭该连接并等待另一个连接请求是常规的?我已经阅读了很多教程和解释,但我无法弄清楚如何正确地做到这一点。也许我错过了一些明显的东西?
如果它有助于查看代码,这就是我正在做的事情:
// Server side setup in the main thread
$this->mConnectionSocket = socket_create(AF_INET, SOCK_STREAM, 0);
$arrOpt = array('l_onoff' => 1, 'l_linger' => 0);
@socket_set_option($this->mConnectionSocket, SOL_SOCKET, SO_LINGER, $arrOpt);
@socket_set_option($this->mConnectionSocket, SOL_SOCKET, SO_REUSEADDR, true);
@socket_bind($this->mConnectionSocket, Hostname, $this->mPortNumber);
@socket_listen($this->mConnectionSocket);
@socket_set_block($this->mConnectionSocket);
.
.
.
// Then call listen(), which looks like this:
public function listen(&$outReadySockets) {
$null = null;
while(true) {
$readyArray = array_merge(array($this->mConnectionSocket), $this->mReceiverSockets);
socket_select($readyArray, $null, $null, $waitTime = null);
if(in_array($this->mConnectionSocket, $readyArray) === true) {
$this->acceptConnection();
$key = array_search($this->mConnectionSocket, $readyArray);
if($key === false) {
throw new IPCException("array_search() returned unexpected value");
} else {
unset($readyArray[$key]);
if(in_array($this->mConnectionSocket, $readyArray) === true) {
throw new IPCException("in_array() says the key is still there");
}
}
}
if(count($readyArray) > 0) {
$outReadySockets = array_merge($readyArray);
break;
}
}
}
// Client side setup in the child thread
$this->mSocket = @socket_create(AF_INET, SOCK_STREAM, 0);
@socket_set_block($this->mSocket);
@socket_connect($this->mSocket, Hostname, $this->mPortNumber);
.
.
.
@socket_write($this->mSocket, $inDataToWrite, $lengthToWrite);
// Main thread reads the socket until it's empty
$data = "";
$totalBytesRead = 0;
while($totalBytesRead < $inNumberOfBytesToRead) {
// Strange that even if we set the socket to block mode, socket_read()
// will not block. If there's nothing there, it will just return an
// empty string. This is documented in the PHP docs.
$tdata = socket_read($inSock, $inNumberOfBytesToRead);
if($tdata === false) {
throw new IPCException("socket_read() failed: " . socket_strerror(socket_last_error()));
} else {
$data .= $tdata;
$bytesReadThisPass = strlen($tdata);
if($bytesReadThisPass === 0) {
break;
}
}
$totalBytesRead += $bytesReadThisPass;
}
.
.
.
// Then calls listen() again
正如我所说,它工作得很好,除了当我listen()
第二次调用时,它告诉我套接字仍然准备好。这似乎是 PHP 文档所说的,但我不希望那样。我想知道那里真的有数据。我做错了吗?还是只是错过了重点?