열려고 하는 포트를 전달한 후 해당 포트에 연결할 수 없거나 포트에서 데이터를 얻을 수 없는 것 같습니다. 내가 작성한 PHP CLI 소프트웨어는 포트에서 적극적으로 수신 대기 중입니다.우분투14.04. 코드의 일부가 아래에 나와 있습니다. 포트는 AF_INET으로 열리고 스크립트는 모든 행에 오류를 발생시키지 않으며 /etc/protocols는 tcp를 "tcp 6 TCP"로 정의합니다.
// I have tried $host=gethostbyname(gethostname());$port=8399 (host is 127.0.1.1)
// as well as $host = '0.0.0.0'; $port = 8399; and other addresses
$this->wsRead[0] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_set_option($this->wsRead[0], SOL_SOCKET, SO_REUSEADDR, 1)
socket_bind($this->wsRead[0], $host, $port)
socket_listen($this->wsRead[0], 10)
while (isset($this->wsRead[0])) { /* Handshake/Process data, etc. */ }
포트가 전달되었습니다.iptables가 비어 있습니다, 해당 포트에 대해 특별히 허용 규칙을 추가하려고 시도했지만. 슈퍼유저로 스크립트를 실행해 보았습니다. 서버가 수신 대기 중일 때 netstat -tuln은 이 행을 나열합니다(포트 8399 사용). Apache도 나열되어 있고 제대로 작동하며 외부 포트 확인 웹 사이트(포트 8301 사용)에서 열린 포트로 표시되는 것을 확인했습니다.
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:8399 0.0.0.0:* LISTEN
tcp6 0 0 :::8301 :::* LISTEN
tcp6 0 0 :::80 :::* LISTEN
nmap을 사용하면 포트도 열려 있는 것처럼 보입니다. 나는 또한 다른 포트를 시도했습니다. 내 클라이언트 연결 스크립트는 Windows에서 PHP CLI를 실행할 때 연결하는 JavaScript 웹소켓 스크립트입니다. 스크립트가 너무 길어 여기에 포함할 수 없으며 외부 네트워크에서 연결되지 않습니다. JS 및 PHP 스크립트를 로컬 주소 127.0.0.1 또는 192.168.0.###으로 설정하면 작동하지만 LAN 외부 장치에서는 작동하지 않습니다.
// The JS is basically this, plus some connection events to alert success/fail.
// This external connection request will always time out
Server = new WebSocket('ws://68.215.154.129:8399');
iptables 외에 우회하지 않는 Linux에 누락된 방화벽이 있습니까? Apache는 PC의 다른 소프트웨어와 마찬가지로 포트를 올바르게 열지만 내 스크립트에는 외부 사용을 위해 포트를 완전히 여는 데 필요한 단계가 누락된 것 같습니다.
TL, PhD; JavaScript 클라이언트를 사용하여 외부 IP 주소를 사용하여 Ubuntu가 아닌 Windows에서 실행되는 PHP 서버에 연결합니다.포트 포워딩, 모니터링, iptables에 의해 차단되지 않음, 무엇이 남았나요?
답변1
개념적으로나 코드에서 뭔가가 누락되었습니다. 연결을 수신하는 PHP 코드가 있지만 이를 사용하기 전에 연결을 수락해야 합니다.
$ns = socket_accept($this->wsRead[0]);
$some_string = socket_read($ns, 128);
블록에 대한 호출입니다 socket_accept()
. 클라이언트 프로그램이 연결을 기다리고 있는 프로그램에 연결될 때까지 반환되지 않습니다.
호출은 socket_accept()
원격 프로그램과 통신하는 데 사용하는 실제 소켓을 반환합니다. 나는 isset()
이것이 정말로 당신이 원하는 것이라고 생각하지 않습니다 . 당신은 그것에 대해 조사해야합니다 socket_select()
. 리모컨과의 통신이 끝나면 호출 socket_close($ns)
한 다음 루프백하여 socket_accept($this->wsRead[0])
다른 원격 프로그램이 사용자 프로그램에 연결될 때까지 기다릴 수 있습니다.
PHP 프로그램이 연결 처리를 마치면 socket_close($this->wsRead[0])
기본적으로 운영 체제 커널에 지정한 포트에서 들어오는 TCP SYN 패킷 수신을 중지하도록 지시하는 닫기 소켓을 호출해야 합니다.
답변2
알고 보니 문제는 주로 모뎀/라우터에서 비롯된 여러 영역에 있었습니다. 나는 하나를 사용모토로라 SB6580, 최근에 펌웨어 업데이트를 했는데 10일 동안 재부팅하지 않아서 속도가 상당히 느려져서 너무 많은 변경을 하고 싶지 않습니다.
이것펌웨어 업데이트로 인해 포트 전달 페이지가 변경됨외부 원격 호스트 주소 부분(기본값은 0.0.0.0)을 포함하는 것은 여기서 문제가 되지 않지만, 내가 설정한 기존 포트 전달 규칙을 위반합니다.
전달할 수 없는 포트 범위를 사용했는데 이 범위를 8399 - 8399로 변경하면 다시 작동하기 시작했습니다. 모뎀 속도를 높이는 것 외에 재부팅해도 아무런 영향을 미치지 않았으며 프로토콜을 둘 다에서 TCP로 변경하지도 않았습니다.
IP Addr|Start Port|End Port|Remote Host Addr|Start Port|End Port|Protocol|Enabled
192.168.0.101|8340| 8399| 0.0.0.0| 8340| 8399| Both|Checked
192.168.0.101|8399| 8399| 0.0.0.0| 8399| 8399| TCP|Checked
또한 Linux에서 PHP 명령 gethostbyname(gethostname())을 사용할 때 반환된 주소는 /etc/hosts 파일의 두 번째 항목인 로컬 주소 127.0.1.1이며 이는 바인딩된 소켓에 적용되지 않습니다. $_SERVER['REMOTE_ADDR']도 다음 경고를 반환합니다. 호스트를 찾을 수 없습니다. 통과집(서브넷?) 주소(내 주소는 192.168.0.101) 또는 IPv4 와일드카드 0.0.0.0으로 수동으로 변경하세요., 소켓 수신기가 올바르게 바인딩되고 외부 연결을 허용합니다.
라우터에 대한 경험과 Linux에 대한 경험 부족으로 인해 Linux 문제 해결에 있어서 잘못된 길로 빠지는 경향이 있었습니다. Windows 7에서도 문제가 제대로 작동하지 않는 것을 확인한 후 위에서 언급한 두 가지 사항을 변경했고 이제 모든 것이 잘 작동합니다.