あなたが抱えている問題は、TCP ストリーミングの性質に関連しています。
サーバーから (たとえば) 100 バイトを送信したという事実は、最初に読み取るときにクライアントで 100 バイトを読み取るという意味ではありません。おそらく、サーバーから送信されたバイトは、いくつかの TCP セグメントでクライアントに到着します。
メッセージ全体が受信されるまで読み取るループを実装する必要があります。DataInputStream
の代わりに を使った例を挙げましょうBufferedinputStream
。ほんの一例を示すのは非常に簡単です。
サーバーが 100 バイトのデータを送信することを事前に知っているとします。
クライアントでは、次のように記述する必要があります。
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
while(!end)
{
int bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == 100)
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
現在、通常、1 つのノード (ここではサーバー) によって送信されるデータ サイズは事前にわかりません。次に、TCP で通信するサーバーとクライアント (または任意の 2 つのノード) 間の通信用に、独自の小さなプロトコルを定義する必要があります。
最も一般的で簡単なのは、TLV (タイプ、長さ、値) を定義することです。したがって、サーバーからクライアントに送信されるすべてのメッセージには、次のものが付属していると定義します。
- タイプを示す 1 バイト (たとえば、2 などでもかまいません)。
- メッセージの長さは 1 バイト (または何でも)
- 値の N バイト (N は長さで示されます)。
したがって、最低 2 バイトを受け取る必要があることがわかり、2 番目のバイトで、次に何バイトを読み取る必要があるかがわかります。
これは、可能なプロトコルの単なる提案です。「タイプ」を取り除くこともできます。
したがって、次のようになります。
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
int bytesToRead = messageByte[1];
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == bytesToRead )
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
次のコードはコンパイルされ、見栄えが良くなります。長さを提供する最初の 2 バイトは、ネットワーク エンディアンシップ (ビッグ エンディアン) のバイナリ形式で到着すると想定しています。残りのメッセージのさまざまなエンコーディング タイプに焦点を当てる必要はありません。
import java.nio.ByteBuffer;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
class Test
{
public static void main(String[] args)
{
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
Socket clientSocket;
ServerSocket server;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);
int bytesToRead = byteBuffer.getShort();
System.out.println("About to read " + bytesToRead + " octets");
//The following code shows in detail how to read from a TCP socket
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length() == bytesToRead )
{
end = true;
}
}
//All the code in the loop can be replaced by these two lines
//in.readFully(messageByte, 0, bytesToRead);
//dataString = new String(messageByte, 0, bytesToRead);
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}