- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我创建了一个到远程服务器的 SocketChannel,以便在 Tomcat 上发送和接收消息。为了从远程计算机接收消息,我使用了一个专用于任务的线程(只有这个线程将从套接字读取,没有其他线程)。
当 SocketChannel 接收到一些字节时(我不断在非阻塞模式下轮询 SocketChannel 以获取新数据),我首先读取 4 个字节以获取下一条消息的长度,然后从 SocketChannel 分配并读取 x 个字节,然后将其解码并重构为消息。
下面是我的接收线程代码:
@Override
public void run() {
while (true) { //Don't exit thread
//Attempt to read the size of the incoming message
ByteBuffer buf = ByteBuffer.allocate(4);
int bytesread = 0;
try {
while (buf.remaining() > 0) {
bytesread = schannel.read(buf);
if (bytesread == -1) { //Socket was terminated
}
if (quitthread) break;
}
} catch (IOException ex) {
}
if (buf.remaining() == 0) {
//Read the header
byte[] header = buf.array();
int msgsize = (0xFF & (int)header[0]) + ((0xFF & (int)header[1]) << 8)
+ ((0xFF & (int)header[2]) << 16) + ((0xFF & (int)header[3]) << 24);
//Read the message coming from the pipeline
buf = ByteBuffer.allocate(msgsize);
try {
while (buf.remaining() > 0) {
bytesread = schannel.read(buf);
if (bytesread == -1) { //Socket was terminated
}
if (quitthread) break;
}
} catch (IOException ex) {
}
parent.recvMessage(buf.array());
}
if (quitthread) {
break;
}
}
}
我从 SocketChannel 收到的第一个字节很好,并且我成功解码了消息。然而,下次我从 SocketChannel 读取时,套接字向前跳过了大约 100 个字节,这导致读取错误的字节并将其解释为长度,从而导致所有内容都损坏。
代码有什么问题吗?没有其他线程正在从 SocketChannel 读取数据。
最佳答案
你的括号被去掉,代码是:
(0xFF & ((int)header[1] << 8))
始终为 0(与 << 16 和 << 24 相同),我猜你的意思是:
((0xFF & ((int)header[1])) << 8)
这会导致读取的消息字节不足,还会导致同步不匹配(而不是读取太多消息字节。)
编辑:现在您已修复上述问题,我看不出有什么问题。你能告诉我们第一条消息的长度和被吃掉的确切字节数之间的关系吗?
根据显示的代码,我唯一的猜测是您从显示的示例中编辑了一些可能影响 schannel 的行为,schannel 是否在其他地方引用?
如果行:
ByteBuffer buf = ByteBuffer.allocate(4);
将位于 while
之外,这会导致您所描述的行为,但在示例代码中并非如此。
关于Java SocketChannel 吃掉我的字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1743124/
长期以来,我一直在寻找解决我的问题的方法,这就是我求助于您的原因: 考虑这段代码: static char done = 0; static void sigHandler(void) { d
我现在的职业是信息架构师和 JavaScript 开发人员,但最近我又回到了后端编码领域。而且,在尝试集成 HTML 原型(prototype)并与我们基于 C# 的 CMS 一起工作时,我与我们的程
我为 Jersey 创建了一个 LoggingFilter,并在 web.xml 中正确配置了它。一切正常。当我执行“GET”时,我得到 userPrincipal (request.getUserP
我没问题 Xcode 8.3.2 和 SourceKitService 正在使用我所有的 CPU。我在stackoverflow上阅读了很多问题,但找不到真正的解决方案。 我试过的: 清理项目数据:c
我是一名优秀的程序员,十分优秀!