당신이 가진 문제는 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();
}
이제 일반적으로 하나의 노드 (여기서 서버)가 전송하는 데이터 크기는 사전에 알려지지 않았습니다. 그런 다음 TCP와 통신하는 서버와 클라이언트 (또는 두 노드) 간의 통신을 위해 자신의 작은 프로토콜을 정의해야합니다.
가장 일반적이고 간단한 것은 TLV : 유형, 길이, 값을 정의하는 것입니다. 따라서 고객에게 전송 된 모든 메시지가 클라이언트에 보내는 것을 정의합니다.
- 1 바이트 표시 유형 (예 : 2 이상일 수도 있음).
- 메시지 길이의 1 바이트 (또는 무엇이든)
- 값에 대한 n 바이트 (n은 길이가 표시됨).
따라서 최소 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();
}
다음 코드가 컴파일되고 더 좋아 보인다. 네트워크 엔디언십 (Big Endian)에서 길이가 이진 형식으로 도착하는 첫 두 바이트가 가정합니다. 나머지 메시지의 경우 다른 인코딩 유형에 중점을 두지 않습니다.
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();
}
}
}