2011-02-08 3 views
1

우선, 시간을내어 읽어 주셔서 감사합니다. 나는 PHP 소켓에 이상한 문제가있다. localhost를 통해 작동하는 php 소켓 데몬에서 작업하고 있지만 LAN이나 다른 PC 외부에서 연결하려고하면 작동하지 않습니다. 내가 볼 수 있도록이 문제를 재현하기 위해 데몬을 매우 기본적인 소켓 연결로 간소화했습니다.PHP 소켓 - 로컬 호스트에서만 연결할 수 있습니다 (포트 포워딩 문제?)

기본적으로 여기에 senario가 있습니다. 포트 6667에있는 서버에서 소켓 데몬을 시작합니다. 데몬을 실행중인 로컬 컴퓨터의 텔넷 및 브라우저를 통해 데몬에 연결할 수 있지만 다른 컴퓨터에서는 액세스 할 수 없습니다. 데몬은 연결 시도를 보지 못합니다 만들어진.

내 포트가 포트 80을 차단하므로 문제가 더 복잡해 지므로 ISP에서 포트 80을 차단하므로 포트 8000을 사용하도록 dyndns와 라우터를 설정했습니다. 앞으로 포트 6667 내 서버에.

내가 다음 (seudo) URL을 입력, 브라우저에서 내 데몬에 액세스하려면 :

http://mydomain.com:8000/client.php 

이 로컬 컴퓨터에서 작동하고 연결되지만, 다른 컴퓨터에서 데몬도하지 않습니다 연결이 시도되고 있는지 확인하십시오. 그러나,이 같은 포트를 지정하는 경우 :

http://mydomain.com:6667 

내 데몬이 만들어지고 연결을 볼 수 없지만, 물론 다음 브라우저 클라이언트 페이지는 사용자가 데몬과 상호 작용하는 데 사용할 수있는로드가 없습니다를 .

클라이언트가 플래시 파일을 사용하여 소켓 연결 (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); 
?> 

요약 :

내가 텔넷을 통해 다른 컴퓨터에서 연결할 수 있습니다,하지만 난에서 연결 수 없습니다 ... 텔넷 및 브라우저를 통해 로컬 호스트에서 연결할 수 있습니다 포트 8000이 지정 될 때 ip 또는 도메인 이름을 사용하는 다른 컴퓨터의 브라우저 디먼에 연결 시도가 표시되지 않습니다. 포트 6667을 지정하면 데몬은 연결 시도를 보지만 사용자에게는 쓸모가 없습니다. :(

이 문제에 어떤 도움을 주시면 감사하겠습니다! 감사합니다!

+0

로컬 컴퓨터의 방화벽은 무엇입니까? –

+0

방화벽이 비활성화되었습니다 ... –

답변

6

당신은 로컬 호스트에 (socket_bind 사용) 소켓을 바인딩하고 있습니다. 로컬 호스트을 공급 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. 
+0

netcoder : 입력 해 주셔서 감사합니다. 실수로 위에 게시 한 코드를 편집하는 것을 잊었습니다. "localhost"로 변경하여 테스트를 수행합니다. 나는 0.0.0.0과 그것을 시도하고 동일한 결과를 얻을. 로컬 시스템은 연결할 수 있지만 데몬은 다른 시스템에서 연결 시도가 보이지 않습니다. –

+0

Linux? Windows? Linux의 경우 SELinux가 활성화되어 있습니까? 라우팅 (예 : iptables)? – netcoder

+0

netcoder : 내 Macbook에서 서비스 중이며 방화벽이 비활성화되어 있습니다. 텔넷을 통해 다른 컴퓨터에서 실제로 연결할 수 있음을 분명히해야합니다 ... 포트 8000을 지정하면 ip 또는 도메인 이름을 사용하여 브라우저에서 연결할 수 없습니다. 디먼에 연결 시도가 표시되지 않습니다. 포트 6667을 지정하면 데몬은 연결 시도를 보지만 사용자에게는 쓸모가 없습니다. ( –

2

나는이 "port_forwarding를 사용합니다. PHP는 "서버에서 포트 3000을 열고 유닉스 소켓 파일/포트 3306에 mysql 서버의 원격 mysql 클라이언트 연결을 전달 :

<? 
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; 
    } 
?> 
관련 문제