首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并不是编写所有的消息( DataOutputStream套接字)

Java并不是编写所有的消息( DataOutputStream套接字)
EN

Stack Overflow用户
提问于 2016-10-13 16:24:51
回答 2查看 486关注 0票数 0

在我的客户机-服务器应用程序中,我发现了一个奇怪的错误。我有以下方法:

代码语言:javascript
复制
sendLoginResponse();
sendPlayerList();
sendCurrentLevelState();

每个方法都向客户端发送一个字节数组。

如果我只调用其中的两个,一切正常工作,客户端将得到所有发送的字节数组。但是,如果我只调用第一个和第二个到达客户端的所有三个方法,那么以下方法的顺序就无关紧要了。但是服务器说他们都是被发送出去的。使用write(byte[] b, int off, int len);方法向客户机iam写入包中的所有长度也是有意义的。奇怪的一点来了:

如果我在第二个方法之后添加了一个Thread.sleep(1000);,那么第三个方法现在就会在睡眠后到达客户机。每次打完电话后,我也试着冲洗DataOutputStream,但这并没有帮助。

编辑:

所以假设我发送了3个登录响应

该方法为我提供了byte[]:

代码语言:javascript
复制
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;
}

而发送方法:

代码语言:javascript
复制
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);
    }
}

因此,如果我连续三次调用sendLoginResponse();,客户端只接收2字节数组,但是服务器说已经发送了3次。如果我添加一个

代码语言:javascript
复制
Thread.sleep(1000); `after the second Method-Call, everything works fine..`

读取消息的客户端在线程中运行:

代码语言:javascript
复制
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);
        }
    }
}

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-13 22:07:14

如果我连续调用sendLoginResponse();三次,客户端只接收2字节数组,但是服务器说已经发送了3次。

这是因为TCP是一种面向流的协议.这意味着它不知道或不关心您的消息是如何被分隔的。TCP中没有单独消息的概念,只是一个字节流,可以保证字节顺序被保留。

因此,当发送方调用三个write时,三个字节数组简单地连接在连接上,并以相同的顺序到达接收方,但是接收方不一定需要三个read来获取所有字节,即使需要三个readread也不一定给出传递给每个对应write的相同字节数组。

您的消息已经具有从字节流中获取单个消息所需的信息:

代码语言:javascript
复制
// 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);
票数 0
EN

Stack Overflow用户

发布于 2016-10-13 21:30:51

DataOutputStream和TCP不会丢失数据。

正如在这种性质的问题中所看到的几乎是不变的,这个问题处于接收端。您可能假设‘`read()’填充了缓冲区,而忽略了它返回的计数。

根据注释中的协议描述,在这种情况下应该使用DataInputStream.readFully()

代码语言:javascript
复制
byte type = din,readByte();
int length = din.readShort();
byte[] data = new byte[length];
din.readFully(data);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40026286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档