PHPでソケットをプログラミングする場合、 socket_accept()は、リスニングソケットに接続されているクライアント接続を受け入れる重要な関数です。ただし、実際の開発中に、 socket_accept()が接続を受信できない状況に遭遇する可能性があります。このタイプの問題はしばしば混乱しています。この記事では、エラーの5つの一般的な原因をリストし、対応するソリューションを提供して、問題を迅速に見つけて解決するのに役立ちます。
問題の説明:
ソケットを作成してアドレスをバインドした後、 socket_listen()が呼び出されない場合、ソケットは接続要求のリスニングを開始せず、 socket_accept()は成功しません。
解決:
socket_accept ()を呼び出す前に、必ずsocket_listen ( )を呼び出してください。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 12345);
socket_listen($socket); // 不可欠
$client = socket_accept($socket);
問題の説明:
バインドするポートが他のプログラムで占有されている場合、 socket_bind()は失敗し、 socket_accept()を含むすべての後続の操作にエラーが発生します。
解決:
ポートが占有されているかどうかを確認するには、 NetStat -TLNPなどのコマンドを使用できます。 GREP 12345 。また、 socket_bind()の返品値を確認し、 socket_last_error()を使用してエラーメッセージを取得します。
if (!socket_bind($socket, '0.0.0.0', 12345)) {
echo "バインディングは失敗しました: " . socket_strerror(socket_last_error($socket));
exit;
}
問題の説明:
サーバーが接続を待っている場合、クライアントはまったく接続しようとせず、間違ったアドレスとポートに接続しないため、当然socket_accept()をトリガーすることはできません。
解決:
たとえば、クライアントの接続アドレスとポートが正しいかどうかを確認してください。
$client = stream_socket_client("tcp://m66.net:12345", $errno, $errstr, 30);
Telnet M66.net 12345を使用して、接続が成功できるかどうかを手動でテストすることもできます。
問題の説明:
socket_accept()は、クライアント接続がない場合に待機するブロッキング関数です。これにより、プログラムが立ち往生しているように見えるかもしれません。
解決:
socket_set_nonblock()を使用して、リスニングソケットを非ブロッキングモードに設定するか、 socket_select()を使用してタイムアウト待機を実装できます。
socket_set_nonblock($socket);
$client = @socket_accept($socket);
if ($client === false) {
echo "現在、接続リクエストはありません\n";
}
または:
$read = [$socket];
$write = $except = [];
if (socket_select($read, $write, $except, 5) > 0) {
$client = socket_accept($socket);
}
問題の説明:
サーバーリスニングポートは正しく設定されていますが、オペレーティングシステムのファイアウォールルールまたはクラウドサーバーのセキュリティグループポリシーは、クライアント接続の要求を防ぎます。
解決:
サーバーのポートを確認して開きます。たとえば、LinuxでiPtablesまたはFirewalldを使用すると、ポート12345にアクセスするか、AWSやAlibaba Cloudなどのクラウドサービスプラットフォームに対応するポートを開くことができます。