PHP 套接字 - 只能从本地主机连接(端口转发问题?)
首先,感谢您花时间阅读本文。我的 PHP 套接字有一个奇怪的问题。我正在开发一个通过本地主机工作的 php 套接字守护进程,但是当我尝试从 LAN 或另一台 PC 外部连接时,它不起作用。我已将我的守护进程简化为一个非常基本的套接字连接,以复制该问题供您查看。
基本上,这就是情况。我在服务器上的端口 6667 上启动套接字守护程序。我可以通过 telnet 并从运行守护程序的本地计算机上的浏览器连接到守护程序,但我不能从任何其他计算机连接到守护程序 - 守护程序甚至看不到连接尝试正在制作中。
为了使问题进一步复杂化(这就是为什么我认为这是端口转发问题),我的 ISP 阻止了端口 80,因此我设置了 dyndns 和我的路由器以使用端口 8000。我还设置了我的路由器以将端口 6667 转发到我的服务器。
要从浏览器访问我的守护程序,我输入以下(伪)url:
http://mydomain.com:8000/client.php
这在本地计算机上工作并将连接,但从任何其他计算机,守护程序甚至看不到正在进行的连接尝试。但是,如果我像这样指定端口:
http://mydomain.com:6667
我的守护程序确实看到正在建立连接,但是浏览器当然不会加载用户可以用来与守护程序交互的客户端页面。
我的客户端使用闪存文件创建套接字连接(jsocket),但我知道它不是跨域策略文件,因为策略是正确的,并且当通过本地主机连接时,它可以正确提供策略文件。
下面是简化的守护进程代码:
<?
// set some variables
$host = '0.0.0.0';
$port = 6667;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
// clean up input string
$input = trim($input);
// echo input back
$output = $input . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
?>
摘要:
我可以通过 telnet 和浏览器从本地主机连接...我可以通过 telnet 从其他机器连接,但当端口 8000 处于连接状态时,我无法使用 ip 或域名从其他机器的浏览器连接指定的。守护进程没有看到任何连接尝试。如果我指定端口 6667,则守护程序会看到连接尝试,但这对用户来说毫无用处。 :(
任何有关此事的帮助将不胜感激!谢谢!
First of all, thanks for taking the time to read this. I have a strange problem with PHP sockets. I working on a php socket daemon which works via localhost, but when I try to connect from outside the LAN or another PC, it doesn't work. I've simplified my daemon to a very basic socket connection to replicate the issue for you to see.
Basically, here's the senario. I start the socket daemon on my server on port 6667. I can connect to the daemon via telnet and from the browser on the local machine running the daemon, but I cannot from any other machine - the daemon doesn't even see a connection attempt being made.
To further complicate the issue (which is why I think it's a port forwarding issue), my ISP blocks port 80, so I've setup dyndns and my router to use port 8000. I've also setup my router to forward port 6667 to my server.
To access my daemon from a browser, I enter the following (seudo) url:
http://mydomain.com:8000/client.php
This works from the local machine and will connect, but from any other machine, the daemon doesn't even see a connection attempt being made. However, if I specify the port like this:
http://mydomain.com:6667
my daemon does see a connection being made, but of course then the browser doesn't have a client page loaded that the user can use to interact with the daemon.
My client uses a flash file to create the socket connection (jsocket), but I know it isn't the cross-domain policy file because the policy is correct, and when connecting via localhost, it serves the policy file correctly.
Here's the simplified daemon code:
<?
// set some variables
$host = '0.0.0.0';
$port = 6667;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
// clean up input string
$input = trim($input);
// echo input back
$output = $input . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
?>
Summary:
I CAN connect from localhost via telnet and browser... I CAN connect from other machines via telnet, but I CAN NOT connection from the browser from other machines using the ip or domain name when port 8000 is specified. The daemon doesn't see any connection attempt. If I specify port 6667, then the daemon see's a connection attempt, but that is useless to the user. :(
Any help in this matter would be greatly appreciated! Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在将套接字(使用 socket_bind)绑定到localhost。提供 localhost 将使 PHP 将套接字绑定到 127.0.0.1。
socket_bind
用于将套接字绑定到特定接口。例如:这允许您连接到 127.0.0.1:80,但不能连接到 192.168.1.100:80,即使它们是同一台计算机。套接字仅绑定到 127.0.0.1 接口:
如果您想在所有可用接口上绑定套接字,请使用:
那么这可以工作:
You're binding the socket (using socket_bind) onto localhost. Supplying localhost there will have PHP bind the socket to the 127.0.0.1.
socket_bind
is used to bind a socket to a specific interface. Per example:This allows you to connect to 127.0.0.1:80, but not 192.168.1.100:80, even if they are the same machine. The socket is bound to the 127.0.0.1 interface only:
If you want to bind the socket on all available interfaces, use:
Then this works:
我在服务器上使用这个“port_forwarding.php”打开端口3000并将远程mysql客户端连接转发到mysql服务器的unix套接字文件/端口3306:
I use this "port_forwarding.php" on server to open port 3000 and forward remote mysql client connection to unix socket file / port 3306 of mysql server: