简体   繁体   English

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

[英]How to read all of Inputstream in Server Socket JAVA

I am using Java.net at one of my project. 我在我的一个项目中使用Java.net。 and I wrote a App Server that gets inputStream from a client. 我写了一个从客户端获取inputStream的App Server。 But some times my (buffered)InputStream can not get all of OutputStream that client sent to my server. 但有时我的(缓冲)InputStream无法获取客户端发送到我的服务器的所有OutputStream。 How can I write a wait or some thing like that, that my InputStream gets all of the OutputStream of client? 我怎么能写一个等待或类似的东西,我的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. 谢谢。

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. 您从服务器发送100字节(例如)的事实并不意味着您第一次阅读时将在客户端中读取100字节。 Maybe the bytes sent from the server arrive in several TCP segments to the client. 也许从服务器发送的字节到达客户端的几个TCP段。

You need to implement a loop in which you read until the whole message was received. 您需要实现一个循环,您可以在其中读取整个消息。 Let me provide an example with DataInputStream instead of BufferedinputStream . 让我提供一个DataInputStream而不是BufferedinputStream的示例。 Something very simple to give you just an example. 给你一个例子非常简单的东西。

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. 最常见也很简单的是定义TLV:Type,Length,Value。 So you define that every message sent form server to client comes with: 因此,您定义从服务器发送到客户端的每条消息都带有:

  • 1 Byte indicating type (For example, it could also be 2 or whatever). 1字节表示类型(例如,它也可以是2或其他)。
  • 1 Byte (or whatever) for length of message 1个字节(或其他)的消息长度
  • N Bytes for the value (N is indicated in length). 值的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). 假设提供长度的前两个字节以二进制格式到达,在网络结束(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();
        }
    }
}
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

You can read your BufferedInputStream like this. 您可以像这样读取BufferedInputStream。 It will read data till it reaches end of stream which is indicated by -1. 它将读取数据,直到到达流的末尾,由-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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM