1

私はJavaサーバーとAndroidクライアントを持っています。クライアントはTCPソケットを介してサーバーに3つのものを送信します。1 つ目は int のファイル サイズ、2 つ目はシリアル番号である long、3 つ目は while ループを使用して pdf ファイルを送信します。

3 つのファイルはすべてサーバーに正常に送信されますが、これを行うには、while ループの直後に両側で出力ストリーム (BufferedOutputStream) を閉じる必要があります。これを行わないと、サーバーに送信される PDF ファイルが不完全になり、破損します。また、プログラムはサーバーのwhileループでブロックまたは凍結され、プログラムの実行は行われなくなります。

問題は、ソケットも閉じるクライアントの出力ストリームを閉じた後、サーバーからクライアントに応答を返すことができないことです。また、クライアント側で新しい入力ストリームを開いてこの応答を受け取ることもできません。

20 の異なる Android クライアントがあるため、サーバーは接続する Android クライアントごとに個別のソケット オブジェクトを起動するため、戻りメッセージが目的の正しいクライアントに確実に返されるようにするには、同じソケットが必要です。

ソケットを開いたままにするにはどうすればよいですか? それでも完全なファイルを送信できますか?

while ループを示すサーバー コードのサンプル

         @Override
        public void run() { // launch new thread

        fileSizeFromClient = dis.readInt();
        serialNumber = dis.readLong();

        byte[] buffer = new byte[fileSizeFromClient];

          while((count = dis.read(buffer)) > 0){
          bos.write(buffer, 0, count);
          }

         bos.close();

         } // end thread

while ループを示すクライアント コードのサンプル

             @Override
             public void run() { // launch new thread

             dos.writeInt((int)length); // sends the length as number bytes is file size
             dos.writeLong(serial); 

                int count = 0; // number of bytes

                while ((count = bis.read(bytes)) > 0) {
                    dos.write(bytes, 0, count);
                }
             dos.flush();
             dos.close();

             } // end thread

観察:

1 - BufferedOutputStream または DataOutputStream オブジェクトのいずれかで close() を呼び出すと、ソケットが閉じられます

2 - クライアントで outputStream.close() が呼び出されない場合、サーバー コードでは while ループでスタックまたはハングし、スレッドの実行は続行されず、ブロックされ、送信された pdf ファイル不完全で破損します

3 - サーバーで outputSteam.close() が呼び出されない場合、上記の 2 のようにサーバー コードがブロックされたりスタックしたりすることはありませんが、送信された pdf ファイルは不完全または破損して到着します。

4 - クライアントとサーバーの両方の出力ストリームで、それぞれの while ループの直後に close() が呼び出された場合、クライアントでもサーバーでも、プログラムの実行にブロックや問題は発生しません。PDFファイルは常に良好な状態で届きます。

編集:私はこれについて完全に間違った方向に進んでいますか? PDFファイルを送信した後にソケットを閉じて、新しいソケットを開いた方が良いですか? その場合、以前のソケットが接続されていたのと同じ Android クライアントで開く方法。他のクライアントではなく、同じ Android クライアントに応答メッセージを送り返したい。

4

1 に答える 1

0

while ループの前にクライアントからファイル サイズを取得しているため、サーバー コードを変更して、ファイル サイズのバイト数のみを読み取り、それらのバイトを受信した後に PDF ストリームを閉じることができます。

byte[] bufferPDF = new byte[fileSizeFromClient];
int count =0;
while (count!=fileSizeFromClient){
   bufferPDF[count]= disSocket.readByte();
   count++;
}
bosPDF.write(bufferPDF);
bosPDF.close();

/** Send response to client **/
dosSocket.write(responseBytes);

クライアント側では、ファイルを送信した後にソケットから読み取ろうとするため、ソケットを閉じる必要はありません。

while ((count = bisPDF.read(bytes)) > 0) {
  dosSocket.write(bytes, 0, count);
}
dosSocket.flush();

while(disSocket.read(responseBytes)>0){
   //Process the response from server
}
于 2013-09-24T06:41:56.793 に答える