【发布时间】: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”是合适的(假设您的变量
conn是java.net.Socket。)“Tcp”是可以的:您的问题不是专门关于 TCP 协议,但它确实与行为有关一个 TCP 套接字。唯一真正不属于这里的标签是“多线程”,因为您对线程一无所知,没有提供与线程相关的代码示例,也没有任何暗示多线程可能与您的问题有关。