如何在Server Socket JAVA中读取所有Inputstream

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19839172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 20:36:42  来源:igfitidea点击:

How to read all of Inputstream in Server Socket JAVA

javanetwork-programminginputstreamserversocketbufferedinputstream

提问by A R

I am using Java.net at one of my project. and I wrote a App Server that gets inputStream from a client. But some times my (buffered)InputStream can not get all of OutputStream that client sent to my server. How can I write a wait or some thing like that, that my InputStream gets all of the OutputStream of client?

我在我的一个项目中使用 Java.net。我编写了一个从客户端获取 inputStream 的应用服务器。但是有时我的(缓冲的)InputStream 无法获取客户端发送到我的服务器的所有 OutputStream。我怎么能写一个等待或类似的东西,我的 InputStream 获取客户端的所有 OutputStream?

(My InputStream is not a String)

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

Thanks.

谢谢。

采纳答案by rodolk

The problem you have is related to TCP streaming nature.

您遇到的问题与 TCP 流媒体性质有关。

The fact that you sent 100 Bytes (for example) from the server doesn't mean you will read 100 Bytes in the client the first time you read. Maybe the bytes sent from the server arrive in several TCP segments to the client.

您从服务器发送 100 字节(例如)这一事实并不意味着您将在第一次读取时在客户端读取 100 字节。也许从服务器发送的字节在几个 TCP 段中到达客户端。

You need to implement a loop in which you read until the whole message was received. Let me provide an example with DataInputStreaminstead of BufferedinputStream. Something very simple to give you just an example.

您需要实现一个循环,您可以在其中阅读直到收到整个消息。让我提供一个例子,DataInputStream而不是BufferedinputStream。一些非常简单的东西只是给你一个例子。

Let's suppose you know beforehand the server is to send 100 Bytes of data.

假设您事先知道服务器要发送 100 字节的数据。

In client you need to write:

在客户端你需要写:

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

Now, typically the data size sent by one node (the server here) is not known beforehand. Then you need to define your own small protocol for the communication between server and client (or any two nodes) communicating with TCP.

现在,通常一个节点(这里是服务器)发送的数据大小事先是未知的。然后,您需要为使用 TCP 通信的服务器和客户端(或任何两个节点)之间的通信定义自己的小协议。

The most common and simple is to define TLV: Type, Length, Value. So you define that every message sent form server to client comes with:

最常见也最简单的就是定义TLV:Type、Length、Value。因此,您定义从服务器发送到客户端的每条消息都带有:

  • 1 Byte indicating type (For example, it could also be 2 or whatever).
  • 1 Byte (or whatever) for length of message
  • N Bytes for the value (N is indicated in length).
  • 1 个字节指示类型(例如,它也可以是 2 或其他)。
  • 消息长度为 1 字节(或其他)
  • 值的 N 字节(N 以长度表示)。

So you know you have to receive a minimum of 2 Bytes and with the second Byte you know how many following Bytes you need to read.

所以你知道你必须至少接收 2 个字节,并且第二个字节你知道你需要读取多少个后续字节。

This is just a suggestion of a possible protocol. You could also get rid of "Type".

这只是一个可能的协议的建议。您也可以摆脱“类型”。

So it would be something like:

所以它会是这样的:

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

The following code compiles and looks better. It assumes the first two bytes providing the length arrive in binary format, in network endianship (big endian). No focus on different encoding types for the rest of the message.

以下代码编译后看起来更好。它假设前两个字节提供的长度以二进制格式到达,网络字节序(大字节序)。没有关注消息其余部分的不同编码类型。

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

回答by Code.me

You can read your BufferedInputStream like this. It will read data till it reaches end of stream which is indicated by -1.

您可以像这样读取 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
}

回答by Devashish Priyadarshi

int c;
    String raw = "";
    do {
        c = inputstream.read();
        raw+=(char)c;
    } while(inputstream.available()>0);

InputStream.available() shows the available bytes only after one byte is read, hence do .. while

InputStream.available() 仅在读取一个字节后显示可用字节,因此执行 .. while