문제

내 프로젝트 중 하나에서 Java.net을 사용하고 있습니다.그리고 클라이언트로부터 inputStream을 얻는 앱 서버를 작성했습니다.그러나 때로는 내 (버퍼링된)InputStream이 클라이언트가 내 서버로 보낸 모든 OutputStream을 가져올 수 없습니다.내 InputStream이 클라이언트의 모든 OutputStream을 가져오는 대기 또는 이와 유사한 내용을 어떻게 작성할 수 있습니까?

(내 입력 스트림은 문자열이 아닙니다)

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();
}

이제 일반적으로 하나의 노드 (여기서 서버)가 전송하는 데이터 크기는 사전에 알려지지 않았습니다. 그런 다음 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();
        }
    }
}

다른 팁

이와 같이 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
}
int c;
    String raw = "";
    do {
        c = inputstream.read();
        raw+=(char)c;
    } while(inputstream.available()>0);

InputStream.available()은 한 바이트를 읽은 후에만 사용 가능한 바이트를 표시하므로 ..~하는 동안

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top