【问题标题】:TCP socket data getting scrambledTCP 套接字数据被打乱
【发布时间】:2016-04-14 06:44:32
【问题描述】:

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

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

应该阅读:

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

ex-- ABCDdddddddddd0000000000WXYZ

我有时读到的:

ex-- 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 - 争夺战的发生方式与之前相同。

【问题讨论】:

  • 我回滚了你上次的编辑。您的编辑使 Peter Lawrey 给出的答案无效。如果您听从了 Peter 的建议,则可以提出一个新问题,或者更新您的问题以添加您尝试过的新事物和看到的新事物。请注意,您实际上还应该包括用于写入数据的代码。问题也可能存在。
  • @Mark Rotteveel-感谢您的建议。从现在开始会这样做。 stackoverflow 世界的新手..
  • 在所有更新和回滚之后,您仍然有一个 read() 方法,其返回值您没有使用。您需要在任何地方使用readFully(),或者不假定read() 填充缓冲区的适当代码。 TCP 是一个字节流,没有义务一次传送超过一个字节。
  • 为什么这个问题被标记为“多线程”?您说代码示例来自多线程程序,但您的问题没有询问任何关于线程的内容,并且您的示例代码没有创建任何线程或执行任何线程同步或线程之间的通信。
  • 好的,所以“Java”是合适的,因为您正在寻找了解 Java 及其库的人; “sockets”是合适的(假设您的变量connjava.net.Socket。)“Tcp”是可以的:您的问题不是专门关于 TCP 协议,但它确实与行为有关一个 TCP 套接字。唯一真正不属于这里的标签是“多线程”,因为您对线程一无所知,没有提供与线程相关的代码示例,也没有任何暗示多线程可能与您的问题有关。

标签: java sockets tcp


【解决方案1】:

当你这样做时

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

这会阻止您在阅读旧消息时阅读下一条消息的一部分。

【讨论】:

  • 我的协议是在客户端设计的,只发送 128 个字节的数据包,最多可以为 4 个字节,因此读取的数据将始终为 128 个字节及其倍数。现在还编辑代码 read 现在是 readfully,所以它可以达到目的。
  • 但我的问题仍然是数据会被打乱/混乱吗?
  • @JayeshTripathi 数据在网络上没有损坏,但如果您没有正确读取它可能会损坏。
  • 所以根据我对代码的编辑和您的建议,它现在应该可以解决问题。对吗?
  • @JayeshTripathi 是的。您可能希望使用 BufferedInputStream 来减少对操作系统的实际读取次数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 2018-11-07
  • 1970-01-01
  • 2012-10-08
  • 2016-12-16
  • 1970-01-01
相关资源
最近更新 更多