現在の位置: ホーム> 最新記事一覧> Socket_set_optionを使用してSO_REUSEADDRを設定してポート職業の問題を​​解決する方法は?

Socket_set_optionを使用してSO_REUSEADDRを設定してポート職業の問題を​​解決する方法は?

gitbox 2025-06-15

Socket_set_optionを使用してSO_REUSEADDRを設定して、ポートが占有されているという問題を解決する方法は?

PHPベースのネットワークアプリケーション、特にリスニングに特定のポートを拘束する必要があるサービス(HTTPサーバー、ソケットサービスなど)を開発する場合、「ポートが占有されている」という問題に遭遇することが一般的です。この問題は通常、サービスが停止した後に発生し、オペレーティングシステムは依然としてポートが占有されていると考えているため、サービスを再起動してポートをバインドできません。

この問題を効果的に解決するために、PHPはsocket_set_option関数を提供します。これは、さまざまなソケットオプションを設定するために使用できます。その中で、 So_ReuseadDRは、ポート占有の問題を解決するのに役立つ一般的に使用されるオプションです。この記事では、 Socket_set_optionを使用してSO_REUSEADDRを設定する方法を詳細に説明して、サービスが再起動したときに使用済みポートを再構築できるようにします。

1。so_reuseaddrとは何ですか?

so_reuseaddrはtime_wait状態の間にポートをバインドできるソケットオプションです。オペレーティングシステムは通常、ポートのステータスをTime_Waitに設定して、すべてのパケットがクリーンアップされていることを確認します。ただし、システムは、他のプロセスがTime_Wait状態でポートに拘束されるのを防ぎます。 SO_REUSEADDRを設定した後、ポートがまだTIME_WAIT状態にある場合は、ポートを再配置できます。

2。Socket_set_option使用してso_reuseaddrを設定します

PHPでは、 socket_set_option関数を使用して、すでに作成されたソケットのオプションを設定します。構文は次のとおりです。

 <span><span><span class="hljs-keyword">bool</span></span><span> </span><span><span class="hljs-title function_ invoke__">socket_set_option</span></span><span> ( resource </span><span><span class="hljs-variable">$socket</span></span><span> , </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$level</span></span><span> , </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$optname</span></span><span> , </span><span><span class="hljs-keyword">mixed</span></span><span> </span><span><span class="hljs-variable">$optval</span></span><span> )
</span></span>
  • $ socket :オプションを設定するソケットリソース。

  • $レベル:プロトコルレイヤー、通常はsol_socketは、ソケットレベルのオプションが操作されることを意味します。

  • $ optnameso_reuseaddrのオプション名、この値はso_reuseaddr (通常1 )です。

  • $ optvalso_reuseaddrの場合、オプション値は通常1であり、オプションが有効になっていることを示します。

3。サンプルコード

socket_set_optionを使用してso_reuseaddrオプションを設定してポートの占有を回避する方法を示す簡単なPHP例を以下に示します。

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-comment">// aを作成します TCP socket</span></span><span>
</span><span><span class="hljs-variable">$socket</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_create</span></span><span>(AF_INET, SOCK_STREAM, SOL_TCP);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$socket</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">"Socket 作成に失敗しました: "</span></span><span> . </span><span><span class="hljs-title function_ invoke__">socket_strerror</span></span><span>(</span><span><span class="hljs-title function_ invoke__">socket_last_error</span></span><span>()) . </span><span><span class="hljs-string">"\n"</span></span><span>;
    </span><span><span class="hljs-keyword">exit</span></span><span>;
}

</span><span><span class="hljs-comment">// 設定 SO_REUSEADDR オプション</span></span><span>
</span><span><span class="hljs-variable">$optval</span></span><span> = </span><span><span class="hljs-number">1</span></span><span>;
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">socket_set_option</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>, SOL_SOCKET, SO_REUSEADDR, </span><span><span class="hljs-variable">$optval</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">"設定 SO_REUSEADDR オプション失败: "</span></span><span> . </span><span><span class="hljs-title function_ invoke__">socket_strerror</span></span><span>(</span><span><span class="hljs-title function_ invoke__">socket_last_error</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>)) . </span><span><span class="hljs-string">"\n"</span></span><span>;
    </span><span><span class="hljs-keyword">exit</span></span><span>;
}

</span><span><span class="hljs-comment">// 指定されたものにバインドします IP およびポート</span></span><span>
</span><span><span class="hljs-variable">$host</span></span><span> = </span><span><span class="hljs-string">'127.0.0.1'</span></span><span>;
</span><span><span class="hljs-variable">$port</span></span><span> = </span><span><span class="hljs-number">8080</span></span><span>;
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">socket_bind</span></span><span>(</span><span><span class="hljs-variable">$socket</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-literal">false</span></span><span>) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"バインディングは失敗しました: "</span></span><span> . </span><span><span class="hljs-title function_ invoke__">socket_strerror</span></span><span>(</span><span><span class="hljs-title function_ invoke__">socket_last_error</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>)) . </span><span><span class="hljs-string">"\n"</span></span><span>;
    </span><span><span class="hljs-keyword">exit</span></span><span>;
}

</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Socket に成功しました <span class="hljs-subst">$host</span></span></span><span>:</span><span><span class="hljs-subst">$port</span></span><span>\n";

</span><span><span class="hljs-comment">// ポートを聞いてください</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">socket_listen</span></span><span>(</span><span><span class="hljs-variable">$socket</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></span><span> . </span><span><span class="hljs-title function_ invoke__">socket_strerror</span></span><span>(</span><span><span class="hljs-title function_ invoke__">socket_last_error</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>)) . </span><span><span class="hljs-string">"\n"</span></span><span>;
    </span><span><span class="hljs-keyword">exit</span></span><span>;
}

</span><span><span class="hljs-comment">// 接続を待っています</span></span><span>
</span><span><span class="hljs-variable">$clientSocket</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_accept</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$clientSocket</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></span><span> . </span><span><span class="hljs-title function_ invoke__">socket_strerror</span></span><span>(</span><span><span class="hljs-title function_ invoke__">socket_last_error</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>)) . </span><span><span class="hljs-string">"\n"</span></span><span>;
    </span><span><span class="hljs-keyword">exit</span></span><span>;
}

</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"クライアントが接続されています!\n"</span></span><span>;

</span><span><span class="hljs-comment">// 接続を閉じます</span></span><span>
</span><span><span class="hljs-title function_ invoke__">socket_close</span></span><span>(</span><span><span class="hljs-variable">$clientSocket</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">socket_close</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>);
</span><span><span class="hljs-meta">?&gt;</span></span><span>
</span></span>

4。コードの説明

  1. ソケットの作成Socket_Create関数を使用してTCPソケットを作成します。この機能は、作成されたソケットを表すリソースを返します。作成が失敗した場合、 falseが返されます。

  2. SO_REUSEADDRオプションを設定するオプションso_reuseaddrをsocket_set_optionに設定して、ポートがtime_wait状態になったときにポートがまだ反抗できるようにします。

  3. バインドポートSocket_Bind関数を使用して、作成したソケットを指定されたIPアドレスとポートにバインドします。バインディングが失敗した場合、プログラムはエラーメッセージを出力します。

  4. リスニングポートsocket_listen関数は、バインドされたポートをリッスンするために使用され、クライアント接続を受け入れる準備ができています。

  5. クライアント接続の受信socket_acceptは待機し、クライアント接続を受け入れます。

5。概要

socket_set_optionso_reuseaddrオプションを設定することにより、特にサービスが再起動する場合、ポート職業の問題を​​効果的に解決できます。このオプションを使用すると、ポートがtime_wait状態の場合にポートを再構築でき、一般的な「ポートが占有されている」エラーを回避できます。

SO_REUSEADDRオプションでは、オペレーティングシステムのポート使用ルールを完全にバイパスできないことに注意してください。主に、ポートがTime_Wait状態にある状況を解決します。他のシナリオで港湾職業に遭遇した場合、より複雑なネットワーク構成またはプロセス管理戦略を検討する必要がある場合があります。