PHP Websocket:socket_recv()和socket_getpeername()的问题
我正在使用PHP Websocket,有时会收到以下两个警告。PHP Websocket:socket_recv()和socket_getpeername()的问题,php,sockets,websocket,Php,Sockets,Websocket,我正在使用PHP Websocket,有时会收到以下两个警告。 警告-1: 套接字_recv():远程主机强制关闭了现有连接 警告2: socket_getpeername():无法检索对等名称[107]:未连接传输终结点 我通过另一个PHP脚本向Websocket发送消息。此PHP脚本发送一条消息,如果消息完成,套接字调用将结束 因此,此警告可能是正确的,因为“端点”(=PHP脚本)未连接记录器。 但是这个警告并不漂亮。 下面是接收消息的Websocket的代码: define('HOST_N
警告-1: 套接字_recv():远程主机强制关闭了现有连接 警告2: socket_getpeername():无法检索对等名称[107]:未连接传输终结点 我通过另一个PHP脚本向Websocket发送消息。此PHP脚本发送一条消息,如果消息完成,套接字调用将结束
因此,此警告可能是正确的,因为“端点”(=PHP脚本)未连接记录器。
但是这个警告并不漂亮。
下面是接收消息的Websocket的代码:
define('HOST_NAME',$host_ip);
define('PORT',$socket_port);
$null = NULL;
$socketHandler = new SocketHandler();
$socketResource = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socketResource, 0, PORT);
socket_listen($socketResource);
$clientSocketArray = array($socketResource);
while (true) {
$newSocketArray = $clientSocketArray;
socket_select($newSocketArray, $null, $null, 0, 10);
if (in_array($socketResource, $newSocketArray)) {
$newSocket = socket_accept($socketResource);
$clientSocketArray[] = $newSocket;
$header = socket_read($newSocket, 1024);
$socketHandler->doHandshake($header, $newSocket, HOST_NAME, PORT);
socket_getpeername($newSocket, $client_ip_address);
$newSocketIndex = array_search($socketResource, $newSocketArray);
unset($newSocketArray[$newSocketIndex]);
}
foreach ($newSocketArray as $newSocketArrayResource) {
while(socket_recv($newSocketArrayResource, $socketData, 1024, 0) >= 1){
$socketMessage = $socketHandler->unseal($socketData);
$messageObj = json_decode($socketMessage);
break 2;
}
$socketData = @socket_read($newSocketArrayResource, 1024, PHP_NORMAL_READ);
if ($socketData === false) {
socket_getpeername($newSocketArrayResource, $client_ip_address);
$newSocketIndex = array_search($newSocketArrayResource, $clientSocketArray);
unset($clientSocketArray[$newSocketIndex]);
}
}
}
socket_close($socketResource);
生成警告-1的命令
套接字_recv():远程主机强制关闭了现有连接
是:
而(socket_recv($newsocketarayresource,$socketData,1024,0)>=1)
在中提到了获取socket_recv()的返回值。但在示例中,只显示了使用if()执行套接字_recv()一次但是我在循环头中使用socket_recv()
所以我的问题是:
在我的例子中,如何检查返回值-在循环头中使用socket_recv() 警告-2 socket_getpeername():无法检索对等名称[107]:未连接传输终结点 已使用以下代码生成: socket\u getpeername($newsocketarray资源,$client\u ip\u地址) 我的问题是:
如果客户端不再连接,我应该怎么做才能不执行socket_getpeername() 也许有人能帮我修复这些警告。很难观看,因为这些警告并不总是出现 再见, 克里斯 在我的例子中,如何检查返回值-在循环头中使用socket_recv() 您可以捕获socket_recv的返回值并检查它的值,但重要的是要按照正确的顺序执行,并且您可以通过使用()来指定php执行的顺序,例如: (但是,请注意,如果您将()放错,它将改为>=的bool结果,例如,这是错误的:
而($bytes\u received=(socket\u recv($newsocketarayresource,$socketData,1024,0)>=1))
,使用此选项,$bytes\u received将改为=/code>的bool结果)
如果客户端不再连接,我应该怎么做才能不执行socket_getpeername()
好的,如果你应用上面的补丁,我想你可以检查$bytes_received是否为true,例如
if (!!$bytes_recieved) {
socket_getpeername($newSocketArrayResource, $client_ip_address);
$newSocketIndex = array_search($newSocketArrayResource, $clientSocketArray);
unset($clientSocketArray[$newSocketIndex]);
}
- 正在执行
将其转换为bool(true ish),如果客户端仍然连接,则可能为true ish,否则可能为false ish。-尽管如此,如果客户端一段时间内没有发送任何字节,这可能会得到误报,因此更安全的方法是直接检查它是否为false,而不是使用false-ish,您可以使用==
,例如
if ($bytes_recieved === false) {
socket_getpeername($newSocketArrayResource, $client_ip_address);
$newSocketIndex = array_search($newSocketArrayResource, $clientSocketArray);
unset($clientSocketArray[$newSocketIndex]);
}
。。。顺便说一句,我不确定,但这里的代码似乎只是随机选择了一个共享$newsocketarayresource的ip地址的客户端,而不是专门选择$newsocketarayresource。如果您的服务器从未收到每个ip地址超过1个连接,我想这是可以的(依我看,这仍然是一个糟糕的设计选择,但没有直接安装错误),但我认为您应该根据资源id而不是ip地址来选择客户机,那么您的服务器将能够支持每个ip地址超过1个连接。我认为您应该将密钥设置为资源id,并执行以下操作:
if ($bytes_recieved === false) {
unset($clientSocketArray[(int)$newSocketArrayResource]);
}
。。。最后,看起来您这里有一个资源泄漏,如果不解决它,将导致内存泄漏(以及处理泄漏),我认为您需要:
if ($bytes_recieved === false) {
unset($clientSocketArray[(int)$newSocketArrayResource]);
socket_close($clientSocketArray);
}
这将使您没有内存/处理泄漏。感谢您的回答。我用“while($bytes_received=socket_recv..”尝试了您的示例,但警告已经出现:“PHP警告:socket_recv():无法从socket读取[10053]:socket错误10053-主机中的软件中止了已建立的连接”。因此,为了获取$bytes_received的返回值,socket_recv()必须首先执行返回值。我想我必须首先检查客户端是否仍然连接,如果仍然连接,我可以调用socket_recv()但是我不知道在执行socket_recv之前我必须检查什么。你有什么想法吗?@Funkfeuer你是在问如何获取socket_recv的返回值并隐藏警告消息
?在这种情况下,答案是而($bytes_received=@socket_recv($newsocketarayresource,$socketData,1024,0))>=1)
是的,你说得对。通过使用while($bytes\u received=@socket\u recv($newsocketarayresource,$socketData,1024,0))>=1)我得到了返回值,但警告仍然伴随着它出现。我该如何处理socket\u recv()是否不生成警告?@Funkfeuer如果警告仍然出现,则在php.ini中将xdebug.scream
设置为0
,或者在抛出警告之前教您的自定义set\u error\u handler()函数检查活动的错误报告()级别。if(!(error\u reporting()&$severity)){/*由于错误而被忽略,报告级别为*/return;}
xdebug说:PHP堆栈跟踪:php1.{main}()C:\xampp\htdocs\TEST\socket\server.PHP:0 php2.socket\recv()C:\xampp\htdocs\TEST\socket\server.PHP:67警告:socket\u recv():无法从socket读取[10053]:主机中的软件中止了已建立的连接。在第67行的C:\xampp\htdocs\TEST\socket\u server.php中,调用堆栈:0.0004 392096 1.{main}()C:\xampp\htdocs\TEST\socket\u server.php:0 77.2232 503704 2.socket\u recv()C:\xampp\htdocs\TEST\socket\u server.php:67
。
if ($bytes_recieved === false) {
unset($clientSocketArray[(int)$newSocketArrayResource]);
socket_close($clientSocketArray);
}