Java 7およびSSLソケットを使用すると、不可解な問題が発生します。
クライアント/サーバーバンドルがあります。どちらも、非常に単純なプロトコルを使用してXMLデータを相互に送信します。各メッセージの最初の4バイトには、常にメッセージ全体の長さが含まれます。つまり、XMLデータの長さに4バイトを加えたものです。
最初に、クライアントはサーバーにグリーティングメッセージを送信します。次に、サーバーはグリーティングを解釈して応答を送信します。次に、クライアント自体がそのメッセージを解釈し、ログイン情報を送信します。サーバーはその情報をチェックし、応答を送り返します。ただし、今回は、サーバーからグリーティング応答を取得する場合とまったく同じ方法を使用しますが、クライアントは何も受信しません。
これは、クライアント側の簡略化された読み取り方法です。
private String readResponse() throws Exception
{
BufferedInputStream inputBuffer = new BufferedInputStream(sslSocket.getInputStream());
// Read and interprete the first 4 bytes to get the length of the XML-data
int messageLength = readMessageLength(inputBuffer) - 4;
// PROBLEM OCCURS HERE!
// Read bufferSize bytes from stream
byte[] byteArray = new byte[messageLength];
inputBuffer.read(byteArray);
// Return the XML-data
return new String(byteArray);
}
そしてここで最初の4バイトから長さを取得するメソッド...
private int readMessageLength(BufferedInputStream in) throws IOException {
byte[] b = new byte[4];
in.read(b, 0, 4);
return (((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff));
}
2番目の応答をクライアントが読み取る必要がある場合、にinputBuffer
はゼロのみが含まれます([0, 0, 0, 0, 0, 0, ...]
)。したがって、を使用してメッセージの長さを計算しようとするとreadMessageLength()
、が返されます-4
。もちろん、それは例外につながります。
サーバーによって送信されたデータがまだクライアントによって読み取られる準備ができていないことは明らかなようです。したがって、私はいくつかの変更を加えました:
int messageLength;
do {
messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);
しかし、それもうまくいきませんでした。そして今、不可解な部分が来ます:何が起こるかというと、このループは2回実行されます!現在割り当てられている値messageLength
は、XMLデータの最初の4バイトから取得されます。reading-methodによって返される文字列は、で始まります?xml
。ここで、<
が欠落しています。
そこで、最初のバイトをマークしてリセットしようとしました。inputBuffer.mark(4);
int messageLength;
do {
inputBuffer.reset();
messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);
しかし、それは実際には無限ループです。内容はinputBuffer
決して変わらないので、。messageLength
以外になることはありません-4
。
クライアントに送信されたデータが利用可能であることをいつ確認できますか?どうすれば確認できますか?より良いアプローチは何でしょうか?
よろしく、ウォルター
PS available()メソッドは、SSLソケットを使用すると常にゼロを返すように見えるため、役に立ちません。