1. ホーム
  2. Java

SocketException java.netの4つの例外解決策。

2022-02-08 04:24:35

より転載 クリックするとリンクが開きます

最初の例外は java.net.BindException:Address already in use.です。JVM_Bindです。

この例外は、サーバー側で新規にServerSocket(port)(portは0, 65536の整数値)の操作を行ったときに発生します。例外が発生する理由は、portと同じと思われるポートが起動され、リッスンしているためです。このとき、netstat -anコマンドを使用すると、Listending状態のポートを確認することができます。占有していないポートを探すだけで、問題を解決できます。

2番目の例外は、java.net.SocketException: 接続が拒否されました: 接続してください。

この例外は、クライアントが新しい Socket(ip, port) 操作を行ったときに発生します。この例外は、ipアドレスを持つマシンが見つからない (つまり、現在のマシンから指定されたipへのルートが存在しない) か、ipは存在するが、指定されたポートをリッスンするために見つからないかのどちらかで発生します。この問題が発生した場合、まずクライアントのipとポートの書き方が間違っていないか確認し、正しい場合はクライアントからサーバーにpingを打ち、pingが通るかどうか確認し、通れば(サービスのサーバー側は別の方法でpingを無効にしている)、サーバー側で指定したポートをリッスンするプログラムが起動するかどうかを確認すれば、確実に問題は解決するはずです。

3つ目の例外は、java.net.SocketException: ソケットが閉じられました。

この例外は、クライアントとサーバーの両方で発生する可能性があります。この例外が発生する理由は、接続が自分の意志で閉じられ(ソケットのcloseメソッドが呼ばれ)、その後、ネットワーク接続の読み取りまたは書き込みが行われたからです。

4つ目の例外は、java.net.SocketException: (Connection reset or Connect reset by peer:Socket write error)です。

この例外は、クライアント側とサーバー側の両方で発生する可能性があります。この例外が発生する理由は2つあります。1つは、ソケットの一方の端が(能動的に、または例外の終了によって)閉じられ、もう一方の端がまだデータを送信している場合、最初に送信したパケットでこの例外(相手による接続リセット)を発生させます。もう一つは、一方の端が終了しても接続が閉じておらず、他方の端が接続からデータを読み出している場合にこの例外(Connection reset)を発生させるものです。簡単に言うと、接続が切れた後の読み書きの操作で発生するものです。

5つ目の例外は、java.net.SocketException: パイプが壊れました。

この例外は、クライアントとサーバーの両方で発生する可能性があります。4番目の例外の最初のケース(つまり、SocketExcepton:Connect reset by peer:Socket write errorを投げた後)では、データの書き込みが続いている場合にスローされます。最初の2つの例外に対する解決策は、まず、プログラムが終了する前にすべてのネットワーク接続を閉じるようにすること、次に、相手が接続を閉じる操作をしたことを発見したら、自分でその接続を閉じるようにすることです。

ネットワークプログラム作成時の留意点

第一の問題は、長い接続と短い接続を正しく区別することです。いわゆるロングコネクションとは、一度確立したら永久に維持されるコネクションのことです。短いコネクションとは、次のようなシナリオで、データを準備する-> コネクションを確立する-> データを送信する-> コネクションをクローズする-ものです。多くのプログラマは、長年ネットワークプログラムを書いていますが、実はロングコネクションとは何か、ショートコネクションとは何かということを知りません。

2つ目の問題は、長い接続を維持することです。メンテナンスとは、第一にアクティブな切断(いずれもソケットのcloseメソッドの呼び出し)を検出すること、第二に相手側のダウンタイム、異常終了、ネットワーク障害を検出することの二つを意味します。これは、堅牢な通信プログラムには必須です。アクティブな切断の検出は簡単で、主側はアクティブに切断し、相手側は読み込み中であれば-1だけを返し、切断を検出したら(ソケットのcloseメソッドを呼んで)積極的に自分の接続を閉じるべきである。

ダウンタイム、異常終了、ネットワーク障害を検出する方法として、通常、"heartbeat"、つまり、双方が定期的に相手側にデータを送信し、また、"heartbeat"を受信する方法が採用されています。を相手側から受信し、相手側が数サイクルにわたってハートビートを受信しない場合は、判断することができます。 相手側から数サイクル連続してハートビートを受信しない場合は、相手側がダウンしているか、異常起動しているか、ネットワークが機能していないと判断できますので、積極的に自分の接続を閉じることが必要です。ソケットには接続を維持するためのkeep aliveオプションがあるが、このオプションを使用した場合、相手側のダウン、異常終了、ネットワークダウンを知るには通常2時間程度かかる。

3つ目の問題は、処理効率の問題である。クライアントであれサーバーであれ、長い接続には、データ受信用とハートビート送信用の、少なくとも2つのスレッドがプログラムに必要です。つまり、受信スレッドはデータを受信し、それをワーカーに配信して処理することだけを担当することになります。ショートコネクションの場合、ハートビート送信スレッドは不要であり、サーバーの場合は接続要求を聞くための特別なスレッドが必要である。以上が通信プログラムの全体的な要件であり、どのようにプログラムを設計するかはあなた次第です。

=======================================================================

. java.net.SocketTimeoutException . この例外はより一般的なもので、ソケットタイムアウトです。一般的にこれが投げられる場所は2つあり、1つは接続時で、connect(SocketAddress endpoint,int timeout)でタイムアウトのパラメータが後者によって決定され、もう1つは読み込み時のタイムアウトを設定する setSoTimeout(int timeout)である。いずれも0を指定することで無限大を示します。
2. java.net.BindException:Address already in use: JVM_Bind . この例外は、サーバー側で新規に ServerSocket(port) または socket.bind(SocketAddress bindpoint) 操作を行った場合に発生します。
原因:portのようなポートが起動し、リッスン中です。この時、netstat -anコマンドを使用すると、Listending状態のポートを確認することができます。占有していないポートを探せば解決します。
3. java.net.ConnectException: 接続が拒否されました:接続 この例外は、クライアントが new socket(ip, port) または socket.connect(address) を実行したときに発生します。この例外は、クライアントが new socket(ip, port) または socket.connect(address, timeout) 操作を行ったときに発生します。
原因:指定したipアドレスのマシンが見つからない(つまり、現在のマシンから指定したipへのルートが存在しない)、またはipは存在するが、指定したポートの待ち受け先が見つからないためです。まず、クライアントのipとポートの書き方が間違っていないか確認し、正しい場合は、クライアントからサーバにpingを打ち、pingが通るかどうか確認し、通れば(サービスのサーバ側はpingを無効にするので別の方法が必要)、サーバ側で指定ポートをリッスンするプログラムが起動するかどうか確認する必要があります。
4. java.net.SocketException: ソケットが閉じられました この例外は、クライアントとサーバーの両方で発生する可能性があります。この例外が発生する理由は、クライアントによって接続が閉じられ(ソケットのcloseメソッドを呼び出した後)、その後、ネットワーク接続の読み取りまたは書き込みが行われたからです。
5. java.net.SocketException: 接続リセットまたは相手による接続リセット:ソケット書き込みエラー . この例外が発生する理由は2つあります。1つは、一方のソケットが(能動的に、または例外の終了によって)閉じられ、もう一方の端がまだデータを送信している場合、最初に送信したパケットによって例外(相手による接続リセット)が発生することです。もう1つは、一方の端が終了しても接続が閉じておらず、もう一方の端が接続からデータを読み込んでいる場合に例外(Connection reset)を発生させることです。簡単に言うと、接続が切れた後の読み書きの操作で発生するものです。
サーバーの場合、一般的な原因は次のように考えることができます。
a) サーバーへの同時接続数がその収容能力を超え、サーバーがその接続の一部を積極的にDownする。
b) データ転送の途中で、ブラウザまたは受信側のクライアントがシャットダウンし、サーバーがまだクライアントにデータを送信中である。
6. java.net.SocketException: 壊れたパイプ . この例外は、クライアントとサーバーの両方で発生する可能性があります。SocketExcepton:Connect reset by peer:Socket write error の後に、データの書き込みが続いている場合にスローされます。最初の2つの例外に対する解決策は、まず、プログラムが終了する前にすべてのネットワーク接続を閉じるようにすること、次に、相手が接続を閉じたことを検知したら接続を閉じるようにすることです。
例外の4と5の2つのケースについては、接続の維持に特別な注意を払う必要があります。短い接続の場合はいいのですが、長い接続の場合は、接続状態の維持が不適切だと、非常に例外が発生しやすくなります。基本的に長い接続のために必要なことは
a) 相手側のアクティブな切断を検出する(相手側がソケットのcloseメソッドを呼び出した)。相手側が接続を読み出している場合、戻り値は-1です。そのため、切断を検出したら、接続を閉じる(ソケットのcloseメソッドを呼び出す)。
b) 相手のダウンタイム、異常終了、ネットワーク障害を検出するためには、ハートビート検出が一般的です。双方は定期的にお互いにデータを送信し、また、&quotを受信する;ハートビートデータ&quot、お互いから、いくつかの連続したサイクルは、お互いのハートビートを受信していない場合は、他の側またはダウンまたは異常終了またはネットワーク障害、この時点でも自分の接続を閉じるには、イニシアチブを取る必要があると判断できる場合、クライアントが再び接続を開始する時間の一定期間遅延する可能性がある場合。クライアントは、特定の遅延後に接続を再初期化することができます。Socketには接続を維持するkeep aliveオプションがありますが、このオプションを使用すると、通常2時間で相手側がダウン、異常終了し、ネットワークがダウンしていることが判明します。
7. java.net.SocketException: 開いているファイルが多すぎます
原因 オペレーティングシステムのオープンファイルハンドルの最大数は制限されています。これは、多くの同時アクセスユーザーがサーバーにアクセスする場合によく起こります。アプリケーションサーバーは、各ユーザーのアプリケーションを実行するために多くのファイルをロードする必要があるため(新しいソケットにはファイルハンドルが必要)、オープンファイルハンドルが不足する結果となります。
解決方法
a) クラスをjarパッケージとして作ってみてください。jarパッケージは1つのファイルハンドルしか消費しませんが、そうでなければ、クラスは1つのファイルハンドルを消費するからです。 

b)  ジャワ GC は、ネットワーク接続によって開かれたファイルハンドルを閉じることができません。close()が実行されない場合、ファイルハンドルは常に存在し、閉じることができません。この問題を制御するために、開いているソケットの最大数を設定することも検討してください。対象 オペレーティングシステム ulimit -a はシステムの現在のリソース制限を確認でき、ulimit -n 10240 はそれを変更できます。