私のプロジェクトの1つでJava.netを使用しています。そして、クライアントからinputStreamを取得するApp Serverを作成しました。ただし、クライアントがサーバーに送信したOutputStreamのすべてを(バッファー付き)InputStreamが取得できない場合があります。 InputStreamがクライアントのすべてのOutputStreamを取得するために、どのように待機またはそのような何かを書くことができますか?
(私のInputStreamは文字列ではありません)
private Socket clientSocket;
private ServerSocket server;
private BufferedOutputStream outputS;
private BufferedInputStream inputS;
private InputStream inBS;
private OutputStream outBS;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
public void getStreamFromClient() {
try {
outBS = clientSocket.getOutputStream();
outputS = new BufferedOutputStream( outBS);
outputS.flush();
inBS = clientSocket.getInputStream();
inputS = new BufferedInputStream( inBS );
} catch (Exception e) {
e.printStackTrace();
}
}
ありがとう。
あなたが持っている問題は、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を定義することです:タイプ、長さ、値。したがって、サーバーからクライアントに送信されるすべてのメッセージには次のものが含まれることを定義します。
したがって、少なくとも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();
}
}
}
int c;
String raw = "";
do {
c = inputstream.read();
raw+=(char)c;
} while(inputstream.available()>0);
InputStream.available()は、1バイトが読み取られた後にのみ使用可能なバイトを表示するため、do .. while
このようにBufferedInputStreamを読み取ることができます。 -1で示されるストリームの終わりに達するまでデータを読み取ります。
inputS = new BufferedInputStream(inBS);
byte[] buffer = new byte[1024]; //If you handle larger data use a bigger buffer size
int read;
while((read = inputS.read(buffer)) != -1) {
System.out.println(read);
// Your code to handle the data
}