我正试图让tcp套接字服务器通过PHP的stream_socket_server()
创建和维护持久的双向通信。
问题的简短版本:
如何在
stream_socket_server()
驻留的情况下创建tcp服务器alive-在第一次成功接收数据后不会失败接收,在我的情况下是telnet后在终端中键入的一个字符命令
长版本-我到底希望实现什么
为了便于说明,请查看使用smtp服务器远程登录某个主机时的通信类型。您输入终端telnet somehost 25
并得到欢迎回复和(通常)smtp横幅并且连接持续存在然后键入hello命令,您将再次获得选项响应,以继续发出进一步的命令再次,连接仍然存在,您得到了响应并可以选择继续。这正是我想要的沟通方式。
到目前为止我做了什么
此代码:
<?php
$server = stream_socket_server("tcp://0.0.0.0:4444", $errno, $errorMessage);
if ($server === false) throw new UnexpectedValueException("Could not bind to socket: $errorMessage");
for (;;) {
$client = stream_socket_accept($server);
if ($client)
{
echo 'Connection accepted from ' . stream_socket_get_name($client, false) . "n";
echo "Received Out-Of-Band: " . fread($client, 1500) . "n";
#fclose($client);
}
}
如果您只是试图通过另一个PHP脚本(即stream_socket_client()
)发送数据(每次拍摄一次),则该方法效果良好。
此脚本创建的服务器无法维护我所描述的连接类型。在完成telnet localhost 4444
之后,我切换到终端模式来写消息。当我这样做的时候,在服务器端我得到了第一个键入的字符,并且-仅此而已。无论我尝试了什么,我都无法通过键入来捕捉客户端发送的新包。像stream_socket_accept()
一样阻塞或忽略接收到的所有第一个字符数据包。那么,我做错了什么——如何解决这个问题?
您的程序在循环返回以接受另一个传入连接之前只进行了一次读取。
fread的文件表明,一旦收到数据包,它就会返回。也就是说,它不会等待完整的1500字节。
考虑到人类打字的速度很慢,您最终会向服务器发送一个带有单个字符的数据包,该数据包会被返回,然后它会接受另一个传入连接。
围绕你的阅读做一个循环:
for (;;) {
$client = stream_socket_accept($server);
if ($client) {
echo 'Connection accepted from ' . stream_socket_get_name($client, false) . "n";
for (;;) {
$data = fread($client, 1500);
if ($data == '') break;
echo "Received Out-Of-Band: " . $data . "n";
}
fclose($client);
}
}