[英]PHP Sockets - can only connect from localhost (Port Forwarding problem?)
首先,感謝您抽出寶貴的時間閱讀本文。 我對PHP套接字有一個奇怪的問題。 我正在通過本地主機工作的php套接字守護程序上工作,但是當我嘗試從LAN或另一台PC外部連接時,它不起作用。 我已將守護程序簡化為非常基本的套接字連接,以復制該問題供您查看。
基本上,這是senario。 我在服務器上的端口6667上啟動了套接字守護程序。我可以通過telnet並從運行守護程序的本地計算機上的瀏覽器連接到守護程序,但不能從任何其他計算機上連接-守護程序甚至看不到連接嘗試被制造。
為了使問題進一步復雜化(這就是為什么我認為這是端口轉發問題),我的ISP阻止了端口80,因此我將dyndns和路由器設置為使用端口8000。我還將路由器設置為將端口6667轉發至我的服務器。
要從瀏覽器訪問守護程序,我輸入以下(偽)URL:
http://mydomain.com:8000/client.php
它可以在本地計算機上工作並可以連接,但是在其他任何計算機上,守護程序甚至都看不到正在進行連接嘗試。 但是,如果我這樣指定端口:
http://mydomain.com:6667
我的守護程序確實看到建立了連接,但是當然瀏覽器沒有加載供用戶用來與守護程序進行交互的客戶端頁面。
我的客戶端使用Flash文件創建套接字連接(jsocket),但是我知道它不是跨域策略文件,因為該策略正確,並且在通過localhost連接時,它可以正確提供該策略文件。
這是簡化的守護程序代碼:
<?
// 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,則守護進程將看到連接嘗試,但這對用戶沒有用。 :(
在這件事上的任何幫助將不勝感激! 謝謝!
您正在將套接字(使用socket_bind )綁定到localhost上 。 在提供localhost的地方,PHP將套接字綁定到127.0.0.1 。
socket_bind
用於將套接字綁定到特定接口。 例如:
socket_bind($socket, '127.0.0.1', 80);
這使您可以連接到127.0.0.1:80 ,但不能連接到192.168.1.100:80 ,即使它們是同一台計算機。 套接字僅綁定到127.0.0.1接口:
$ telnet localhost 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
$ telnet 192.168.1.100 80
Trying 192.168.1.100...
telnet: Unable to connect to remote host: Connection refused
如果要在所有可用接口上綁定套接字,請使用:
socket_bind($socket, '0.0.0.0', 80);
然后工作:
$ telnet localhost 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
$ telnet 192.168.1.100 80
Trying 192.168.1.100...
Connected to 192.168.1.100.
我在服務器上使用此“ port_forwarding.php”打開端口3000,並將遠程mysql客戶端連接轉發到Unix套接字文件/ mysql服務器的端口3306:
<?
set_time_limit(0);
function shutdown()
{global $ipsock, $rmsock;
if ($ipsock) fclose($ipsock);
if ($rmsock) fclose($rmsock);
}
register_shutdown_function('shutdown');
$target_socket='unix:///tmp/mysql.sock';//or 'tcp://192.168.0.2:3306'
$ipsock=stream_socket_server('tcp://192.168.0.2:3000', $errno2, $errstr2);
stream_set_blocking($ipsock, 0);
while (true)
{usleep(5000);//0.005s, to reduce cpu consumption
$c_ipsock=stream_socket_accept($ipsock); //even add '-1', it won't wait
$rmsock=stream_socket_client($target_socket, $errno, $errstr);
@stream_set_blocking($rmsock, 1);
while (($c_ipsock && !feof($c_ipsock)) && ($rmsock && !feof($rmsock)))
{$swrite=$except=null;
$sread=array($c_ipsock, $rmsock);
stream_select($sread, $swrite, $except, 5);
//print_r($sread);echo " \n";
if ($sread[0]===$rmsock)
{if ($data=fread($rmsock, 65536))
{//echo 'rmsock:'.strlen($data).' '.$data." \n";
myfwrite($c_ipsock, $data);
}
}
else if ($sread[0]===$c_ipsock)
{if ($data=fread($c_ipsock, 65536))
{//echo 'ipsock:'.strlen($data).' '.$data." \n";
myfwrite($rmsock, $data);
}
}
//var_export(array(feof($c_ipsock), feof($rmsock)));echo " \n";
}
@fclose($c_ipsock);
@fclose($rmsock);
}
function myfwrite($fd,$buf) {
$i=0;
while ($buf != "") {
$i=fwrite ($fd,$buf,strlen($buf));
if ($i==false) {
if (!feof($fd)) continue;
break;
}
$buf=substr($buf,$i);
}
return $i;
}
?>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.