PHPを使用してソケットベースのサーバーアプリケーションを作成する場合、 socket_accept()はクライアント接続を受信する重要な関数です。ただし、いくつかのシナリオでは、プログラムロジックが正しい場合でも、 socket_accept()は正常に接続を受信しない場合があります。この記事では、 StraceおよびNetstatツールを使用して、この問題を迅速に見つけて解決する方法について説明します。
以下は、ポート8080に耳を傾ける簡単なPHPサーバープログラムです。
<?php
$host = '0.0.0.0';
$port = 8080;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);
echo "Server listening on $host:$port\n";
while (true) {
$client = socket_accept($socket);
if ($client === false) {
echo "Failed to accept connection\n";
continue;
}
$msg = "Hello from server\n";
socket_write($client, $msg, strlen($msg));
socket_close($client);
}
?>
socket_accept()がスタックしているか、常にfalseを返す場合、システムツールを使用して詳細なトラブルシューティングを実行する必要があります。
Straceは、Linuxの下のシステムコールトラッキングツールです。実行時にPHPスクリプトと実行結果によって呼び出されるシステムの基礎関数がどのシステムを表示するかを直接表示できます。
たとえばPSを使用するなど、実行中のPHPプロセスPIDを見つけます:
ps aux | grep php
Straceを使用してプロセスに接続します。
strace -p <PID> -e trace=network
次の動作が出力に存在するかどうかを観察します。
Accept(...)= -1 :システムコールが失敗しました。通常、エラーコード(イーガイン、エコナボートなど)が伴います。
聞く(...)またはバインド(...)エラー:ポートが占有されているか、許可が不十分であることを意味する場合があります
承認する呼び出しはありません() :プログラムは他の場所で立ち往生する可能性があります
StraceがAccept()が正常であるが接続アクセスがないことを示す場合、問題はネットワークレイヤーまたはファイアウォールにある可能性があります。
NetStatおよびSSを使用して、ポートがリスニング状態にあるかどうか、および接続が確立されているかどうかを確認できます。
netstat -tlnp | grep :8080
または:
ss -tlnp | grep :8080
次のような出力を見ることができるはずです。
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("php",pid=12345,fd=3))
リスニングがない場合、 socket_bind()またはsocket_listen()が失敗します。
リスニングが正常であるが接続がない場合、クライアントが接続を開始していないか、ファイアウォールによって傍受される可能性があります。
ステータスがclose_waitまたはtime_waitの場合、接続ライフサイクルが異常に終了することを意味します。
エラーメッセージを確認してください<br> 各ソケット呼び出しの後、 socket_strerror(socket_last_error())を使用して、特定のエラー情報を表示します。
ファイアウォールまたはSelinuxの制限<br> IPTablesまたはFirewalldを使用して、8080ポートがブロックされていないことを確認します。
ポートは他のプログラム<br>によって占有されています LSOF -I:8080を使用して、他のプログラムがポートを占めるかどうかを確認します。