TCP套接字数据被加扰

时间:2016-04-14 06:44:33

标签: java sockets tcp

我有一个多线程TCP套接字侦听程序。我对特定字节数(128字节和4xmultiples)的数据执行了阻塞读取,因此我的数据包大小为128字节,256字节,384字节和512字节。

我遇到了问题,因为有时数据会在套接字中混乱。例如:

原定阅读:

<header><data payload(padded with zeros to compensate size)><footer>

前 - ABCDddddddddd0000000000WXYZ

我有时读到的内容:

前 - ABCDdd00000000000000000dddddd00

然后下一个数据包看起来像

00000WXYZABCDddddd00000000000000000

所以我关闭了套接字,我们已经定义了协议来发回2或3个旧数据包以避免丢失。

我的问题是

1。为什么数据会被扰乱/混乱?

2。可以通过任何方式避免吗?

这是我的读取数据代码。

in = new DataInputStream(conn.getInputStream());
outStream = conn.getOutputStream();
while (m_bRunThread) {
    // read incoming stream
    in.readFully(rec_data_in_byte, 0, 128); //blocks until 128 bytes are read from the socket
    {
        //converting the read byte array into string
        //finding out the size from a particular position,helps determine if any further reads are required or not.
        //if the size is a multiple of 128 and the size is a multiple higher than 1 then more reads are required.
        if ((Integer.parseInt(SIZE) % 128 == 0) && ((SIZE / 128) > 1)) {
            for(int z = 1;z < lenSIZE;z++) {
                in.readFully(rec_data_in_byte1, 0, 128);//changed from in.read(rec_data_in_byte1, 0, 128); as per suggestions
            }
            //extracting the data,validating and processing it
        }
    } 
}

更新 已实施 Peters 修复,但问题仍然存在。数据正在变得混乱。 添加几行额外代码,将字节数组转换为字符串。

byte[] REC_data=new byte[1024];
System.arraycopy(rec_data_in_byte1, 0, REC_data, 128*z, 128);
rec_data_string=MyClass2.getData(REC_data,0,Integer.parseInt(SIZE)-1,Integer.parseInt(SIZE));

getdata()方法如下:

String msg = "";//the return String
    int count = 1;
    for (int i = 0; i < datasize; i++) {
        if (i >= startindex) {
            if (count <= lengthofpacket) {
                msg += String.valueOf((char) (bytedata[i]));
                count++;
            }
        }
    }
    return msg;

这可能是争抢的原因吗?

P.S - 争夺的发生方式与之前发生的方式相同。

1 个答案:

答案 0 :(得分:2)

当你这样做时

int lengthActuallyRead = in.read(rec_data_in_byte1, 0, 128);

您需要检查读取的长度。否则它可能会读取1个字节,或者在这种情况下最多可读取128个字节。请注意,实际读取的内容之后的任何字节都不会受到影响,因此它们可能是0,或者它们可能是前一条消息中的垃圾。

如果您希望使用128字节,则可以像以前一样使用readFully

in.readFully(rec_data_in_byte, 0, 128);

注意:如果剩余金额少于128,您可能需要这样做。

int remaining = size - sizeReadSoFar;
int length = in.read(rec_data_in_byte1, 0, remaining);

这可以防止您在阅读旧邮件时阅读下一条邮件的一部分。