简体   繁体   English

Java DataOutputStream不会写入所有消息(TCP套接字)

[英]Java DataOutputStream doesnt write all messages ( TCP Socket )

in my Client-Server application I found a strange error. 在我的客户端服务器应用程序中,我发现了一个奇怪的错误。 I got the following Methods : 我有以下方法:

sendLoginResponse();
sendPlayerList();
sendCurrentLevelState();

Each Methods sends a byte array to the Client-Side 每个方法将字节数组发送到客户端

If I only call 2 of them, everything works fine and the Client-Side gets all the sent byte arrays. 如果我只调用其中的2个,则一切正常,客户端将获取所有已发送的字节数组。 But if I call all 3 of them only the first and second one arrive the Client, the order of the following methods doesnt matter. 但是,如果我将它们中的全部三个都称为第一个和第二个到达客户端,则以下方法的顺序无关紧要。 but the Server says all of them were send. 但是服务器说所有的都发送了。 To write to the Client iam using the write(byte[] b, int off, int len); 使用write(byte[] b, int off, int len);向客户端iam write(byte[] b, int off, int len); method all The lenghts within the packages make sense too. 全部使用方法包中的长度也很有意义。 Here comes the strange point: 奇怪的是:

if I add a Thread.sleep(1000); 如果我添加Thread.sleep(1000); after the second Method, the third one does now arrive the Client after the sleep. 在第二种方法之后,第三种方法确实在睡眠后到达客户端。 I Have also tried to flush the DataOutputStream after every write call, but this didnt help. 我也尝试在每个写调用之后刷新DataOutputStream,但这没有帮助。

EDIT: 编辑:

So let's say I'd send 3 Login-Response 假设我要发送3个登录响应

The Method's that gives me the byte[]: 该方法给了我byte []:

public byte[] getLoginResponse(int playerID){
    byte[] msg = new byte[4];
    short shortMsgLength = 4;
    byte[] msgLength = shortToBytes(shortMsgLength);
    msg[0] = 2;
    msg[1] = msgLength[0];
    msg[2] = msgLength[1];
    msg[3] = (byte) playerID;
    return msg;
}

private byte[] shortToBytes(short value) {
    byte[] returnByteArray = new byte[2];
    returnByteArray[0] = (byte) (value & 0xff);
    returnByteArray[1] = (byte) ((value >>> 8) & 0xff);
    return returnByteArray;
}

And the Send Method: 和发送方法:

private void sendLoginResponse() {
    try{
        byte[] msg = rfcObject.getLoginResponse(playerID);
        out.write(msg,0,msg.length);
    }catch(Exception e){
        System.err.println(e.getMessage());
        System.exit(0);
    }
}

So if I call the sendLoginResponse(); 因此,如果我调用sendLoginResponse(); three times in a row, the client only recieves 2 byte-arrays, but the server says it has been sent 3 times. 客户端连续连续3次接收2个字节数组,但服务器表示已发送3次。 If i add a 如果我添加一个

Thread.sleep(1000); `after the second Method-Call, everything works fine..`

The Client that reads the message runs in a Thread: 读取消息的客户端在线程中运行:

public void run(){
    while(true){
        try {
            byte[] data = new byte[MAX_DATA_SIZE]; // MAX_DATA = 255
            byteCount = in.read(data);

        } catch (IOException ex) {
            handleExceptionError(ex);
        }
    }
}

thank you! 谢谢!

DataOutputStream and TCP don't lose data. DataOutputStream和TCP不会丢失数据。

As almost invariable seen in questions of this nature, the problem is at the receiving end. 从这种性质的问题中几乎可以看出,问题在接收端。 You are probably assuming that `read()' fills the buffer, and ignoring the count that it returns. 您可能假设`read()'填充了缓冲区,而忽略了它返回的计数。

Based on your protocol description in comments, you should be using DataInputStream.readFully() in this circumstance: 根据注释中的协议描述,在这种情况下,应使用DataInputStream.readFully()

byte type = din,readByte();
int length = din.readShort();
byte[] data = new byte[length];
din.readFully(data);

if I call the sendLoginResponse(); 如果我调用sendLoginResponse(); three times in a row, the client only recieves 2 byte-arrays, but the server says it has been sent 3 times. 客户端连续连续3次接收2个字节数组,但服务器表示已发送3次。

This is because TCP is a stream-oriented protocol. 这是因为TCP是面向流的协议。 Meaning it doesn't know or care how your messages are delimited. 意味着它不知道或不在乎您的消息如何分隔。 There's no concept of individual messages in TCP, just a stream of bytes, with the guarantee that the order of bytes is preserved. 在TCP中没有单独消息的概念,只是字节流,并保证字节顺序得以保留。

So when the sender calls three write , the three byte arrays are simply concatenated over the connection and arrives at the receiver in the same order, but the receiver doesn't necessarily need three read to get all the bytes, and even if it does take three read , the read doesn't necessarily gives you the same byte array passed to each corresponding write . 因此,当发送方调用三个write ,这三个字节数组将简单地通过连接进行连接,并以相同的顺序到达接收方,但是接收方不一定需要进行三个read即可获取所有字节,即使它确实需要三readread不一定给您传递到每个对应write的相同字节数组。

Your message already have the necessary information to get the individual message back from the byte stream: 您的消息已经具有必要的信息,可以从字节流中获取单个消息:

// Client code for reading individual messages from a TCP connection

byte type = din.readByte();

// Read the message length, little-endian.
// We cannot use din.readShort because it's big-endian
int lenLo = din.read();
int lenHi = din.read();
short len = (short)(lenLo | (lenHi << 8));
byte [] body = new byte[len];
din.readFully(body);

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

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