現在の位置: ホーム> 最新記事一覧> PHPのGetServbyNameを使用して、サービス名が有効かどうかを判断する方法は?

PHPのGetServbyNameを使用して、サービス名が有効かどうかを判断する方法は?

gitbox 2025-09-12

PHPでは、 GetServbyName(String $ Service、String $ Protocol)は、サービス名( HTTPSSHなど)およびプロトコル( TCPまたはUDPなど)に基づいて、対応するポート番号(10進整数)を返すことができます。サービス名が見つからない場合、またはエラーが発生した場合、関数はfalseを返します。したがって、それを使用して、システムサービスデータベースにサービス名が存在するかどうかを判断できます(Linuxの下の/etc /サービス、Windowsのサービスファイルなど) - 注:これは、サービスが現在接続されているか利用可能かを確認するのではなく、名前がポートにマッピングされているかどうかを確認するためです。

次の例は、一般的な使用状況、カプセル化関数、考慮事項、および実際の可用性のための追加の検出方法を示しています(サービスが本当に接続されていることを確認する必要がある場合)。


基本的な使用法

<span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-variable">$service</span></span><span> = </span><span><span class="hljs-string">'http'</span></span><span>;
</span><span><span class="hljs-variable">$protocol</span></span><span> = </span><span><span class="hljs-string">'tcp'</span></span><span>;

</span><span><span class="hljs-variable">$port</span></span><span> = </span><span><span class="hljs-title function_ invoke__">getservbyname</span></span><span>(</span><span><span class="hljs-variable">$service</span></span><span>, </span><span><span class="hljs-variable">$protocol</span></span><span>);

</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$port</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"サービス名 '<span class="hljs-subst">{$service}</span></span></span><span>'(プロトコル </span><span><span class="hljs-subst">{$protocol}</span></span><span>)ネイティブサービスデータベースには存在しません。\n";
} </span><span><span class="hljs-keyword">else</span></span><span> {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"仕える '<span class="hljs-subst">{$service}</span></span></span><span>'(</span><span><span class="hljs-subst">{$protocol}</span></span><span>)ポートにマップします:</span><span><span class="hljs-subst">{$port}</span></span><span>\n";
}
</span></span>

推奨判断カプセル化機能

この関数は、より堅牢な判断を下します。GetServbyName返品値を確認し、ポート番号が法的範囲(1–65535)内にあることを確認してください。

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
<span class="hljs-comment">/**
 * 判断サービス名称是否有效(在このマシン仕える数据库中有对应端口)
 *
 * </span></span><span><span class="hljs-doctag">@param</span></span><span> string $service サービス名称,例えば 'http'、'ssh'
 * </span><span><span class="hljs-doctag">@param</span></span><span> string $protocol プロトコル 'tcp' または 'udp'
 * </span><span><span class="hljs-doctag">@return</span></span><span> bool 戻る true それは有効なことを意味します(法的ポートを見つけます),false 表示无效または出错
 */
</span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">is_service_name_valid</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-keyword">string</span></span></span><span> </span><span><span class="hljs-variable">$service</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$protocol</span></span><span> = </span><span><span class="hljs-string">'tcp'</span></span><span>): </span><span><span class="hljs-title">bool</span></span><span>
{
    </span><span><span class="hljs-comment">// 正規化されたパラメーター</span></span><span>
    </span><span><span class="hljs-variable">$protocol</span></span><span> = </span><span><span class="hljs-title function_ invoke__">strtolower</span></span><span>(</span><span><span class="hljs-variable">$protocol</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (!</span><span><span class="hljs-title function_ invoke__">in_array</span></span><span>(</span><span><span class="hljs-variable">$protocol</span></span><span>, [</span><span><span class="hljs-string">'tcp'</span></span><span>, </span><span><span class="hljs-string">'udp'</span></span><span>], </span><span><span class="hljs-literal">true</span></span><span>)) {
        </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">false</span></span><span>;
    }

    </span><span><span class="hljs-variable">$port</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">getservbyname</span></span><span>(</span><span><span class="hljs-variable">$service</span></span><span>, </span><span><span class="hljs-variable">$protocol</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$port</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
        </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">false</span></span><span>;
    }

    </span><span><span class="hljs-comment">// ポートが法的範囲であることを確認してください</span></span><span>
    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-title function_ invoke__">is_int</span></span><span>(</span><span><span class="hljs-variable">$port</span></span><span>) &amp;&amp; </span><span><span class="hljs-variable">$port</span></span><span> &gt;= </span><span><span class="hljs-number">1</span></span><span> &amp;&amp; </span><span><span class="hljs-variable">$port</span></span><span> &lt;= </span><span><span class="hljs-number">65535</span></span><span>;
}

</span><span><span class="hljs-comment">// 例</span></span><span>
</span><span><span class="hljs-title function_ invoke__">var_dump</span></span><span>(</span><span><span class="hljs-title function_ invoke__">is_service_name_valid</span></span><span>(</span><span><span class="hljs-string">'http'</span></span><span>, </span><span><span class="hljs-string">'tcp'</span></span><span>));  </span><span><span class="hljs-comment">// 一般的に true</span></span><span>
</span><span><span class="hljs-title function_ invoke__">var_dump</span></span><span>(</span><span><span class="hljs-title function_ invoke__">is_service_name_valid</span></span><span>(</span><span><span class="hljs-string">'nosuchservice'</span></span><span>, </span><span><span class="hljs-string">'tcp'</span></span><span>)); </span><span><span class="hljs-comment">// false</span></span><span>
</span></span>

プラットフォームの依存関係と制限(重要)

  • GetServbyNameは、オペレーティングシステムのサービスデータベース/etc /servicesなど)を照会します。異なるシステム、異なるインストール環境、および異なる分布には、異なるエントリが含まれる場合があります。たとえば、一部のカスタムサービスは1つのホストに存在し、別のホストではありません。

  • この関数は、サービス名にポートマップがあるかどうかのみを示します。そのポート上のサービスが現在実行または接続されていることを意味しません。 「サービスの可用性」を確認する必要がある場合は、ネットワーク接続テスト( FSOCOPENStream_Socket_ClientSocket_Create / socket_connectなど)を実行する必要もあります。

  • プロトコルは「TCP」または「UDP」 (ケース非感受性)でなければなりません。他の値は無効と見なされます。

また、サービスが接続可能かどうかを確認したい場合(オプション)

サービス名の存在を決定することは、最初のステップにすぎません。リモートホスト(またはローカルホスト)がそのサービスポートの接続を受け入れるかどうかを確認する場合は、最初にgetServbyNameを使用してポートを取得してから、接続を確立することができます。

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
<span class="hljs-comment">/**
 * 最初に使用します getservbyname 判断サービス名,アクセシビリティを確認するために、ターゲットホストのポートに接続してみてください
 *
 * </span></span><span><span class="hljs-doctag">@param</span></span><span> string $host ターゲットホスト(IP または ホスト名)
 * </span><span><span class="hljs-doctag">@param</span></span><span> string $service サービス名称
 * </span><span><span class="hljs-doctag">@param</span></span><span> string $protocol 'tcp' または 'udp'(ここでのみ実装されています tcp 接続検出)
 * </span><span><span class="hljs-doctag">@param</span></span><span> float $timeout 2番(例えば 2.0)
 * </span><span><span class="hljs-doctag">@return</span></span><span> bool true ポートが見つかり、確立できることを示します TCP 接続する,false さもないと
 */
</span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">is_service_reachable</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-keyword">string</span></span></span><span> </span><span><span class="hljs-variable">$host</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$service</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$protocol</span></span><span> = </span><span><span class="hljs-string">'tcp'</span></span><span>, </span><span><span class="hljs-keyword">float</span></span><span> </span><span><span class="hljs-variable">$timeout</span></span><span> = </span><span><span class="hljs-number">2.0</span></span><span>): </span><span><span class="hljs-title">bool</span></span><span>
{
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">strtolower</span></span><span>(</span><span><span class="hljs-variable">$protocol</span></span><span>) !== </span><span><span class="hljs-string">'tcp'</span></span><span>) {
        </span><span><span class="hljs-comment">// 単純化します:ここでのみ行います TCP 接続検出;UDP より複雑な検出(无接続する/確認なし)</span></span><span>
        </span><span><span class="hljs-keyword">throw</span></span><span> </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-built_in">InvalidArgumentException</span></span><span>(</span><span><span class="hljs-string">'is_service_reachable 現在、サポートされています tcp テスト'</span></span><span>);
    }

    </span><span><span class="hljs-variable">$port</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">getservbyname</span></span><span>(</span><span><span class="hljs-variable">$service</span></span><span>, </span><span><span class="hljs-variable">$protocol</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$port</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span> || !</span><span><span class="hljs-title function_ invoke__">is_int</span></span><span>(</span><span><span class="hljs-variable">$port</span></span><span>) || </span><span><span class="hljs-variable">$port</span></span><span> &lt; </span><span><span class="hljs-number">1</span></span><span> || </span><span><span class="hljs-variable">$port</span></span><span> &gt; </span><span><span class="hljs-number">65535</span></span><span>) {
        </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">false</span></span><span>;
    }

    </span><span><span class="hljs-variable">$errno</span></span><span> = </span><span><span class="hljs-number">0</span></span><span>;
    </span><span><span class="hljs-variable">$errstr</span></span><span> = </span><span><span class="hljs-string">''</span></span><span>;
    </span><span><span class="hljs-variable">$fp</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">fsockopen</span></span><span>(</span><span><span class="hljs-variable">$host</span></span><span>, </span><span><span class="hljs-variable">$port</span></span><span>, </span><span><span class="hljs-variable">$errno</span></span><span>, </span><span><span class="hljs-variable">$errstr</span></span><span>, </span><span><span class="hljs-variable">$timeout</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$fp</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
        </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">false</span></span><span>;
    }

    </span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$fp</span></span><span>);
    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}

</span><span><span class="hljs-comment">// 例</span></span><span>
</span><span><span class="hljs-title function_ invoke__">var_dump</span></span><span>(</span><span><span class="hljs-title function_ invoke__">is_service_reachable</span></span><span>(</span><span><span class="hljs-string">'127.0.0.1'</span></span><span>, </span><span><span class="hljs-string">'ssh'</span></span><span>, </span><span><span class="hljs-string">'tcp'</span></span><span>, </span><span><span class="hljs-number">1.5</span></span><span>)); </span><span><span class="hljs-comment">// このマシン ssh 仕える是否可达</span></span><span>
</span></span>

注:UDPの「Reachability」判断は単純な接続ではありません。通常、プローブパケットを送信して応答を待つか、より複雑なソケットAPIを使用する必要があります(ファイアウォールによって破棄される場合があります)。 UDP検出が実際に必要な場合は、アプリケーションレイヤー検出ロジックを実装するか、特殊なツールを使用します。

一般的なユースケースと提案

  1. 構成検証:ユーザーが構成インターフェイスでサービス名( SMTPIMAPなど)を入力すると、最初にgetServbyNameを使用して、名前がシステムによって認識されているかどうかを確認します。認識されていない場合、ユーザーはポート番号を使用するか、別のサービス名を選択するように求められます。

  2. 互換性:システムのサービスデータベースに依存しないでください - クロスプラットフォームの一貫性が必要な場合、フォールバックとしてアプリ内マッピングテーブル( 'http' => 80など)を維持します。

  3. 許可とセキュリティ:アクセシビリティ検出のためにポートを接続しようとする場合、ネットワークポリシー、ファイアウォール、レート制限に注意してください。虐待やセキュリティアラームのトリガーを避けるために、短期間で多数のホストを頻繁に検出しないでください。

  4. エラー処理GetServbyNameはFalseを返す場合があります。返品値を直接使用する代わりに、コードで明示的に処理してください。

まとめ

  • getServbyName($ service、$ protocol)を使用して、サービス名にローカルシステムサービスデータベースにポートマップがあるかどうかを判断します(ポート番号またはfalseを返します)。

  • 妥当性を判断するときに返品値の種類を確認し、ポートが1〜65535の範囲内にあることを確認するのが最善です。

  • この方法は、サービスが利用可能であることを意味するものではありません。可用性が必要な場合は、ネットワーク接続レベル( FSOCCKOPENなど)でさらに検出する必要があります。

  • プラットフォームの違いに注意してください:さまざまなシステムのサービスデータベースエントリは異なります。クロスプラットフォームの要件がある場合は、フォールバックマッピングの準備をするか、ユーザーにポート番号の提供を依頼してください。