我正在使用 java 1.6 开发即时通讯工具。IM 使用多线程 - 主线程、接收和 ping。对于 tcp/ip 通信,我使用了 SocketChannel。从服务器接收更大的包裹似乎存在问题。服务器而不是一个发送几个包,这就是问题开始的地方。每前 8 个字节说明包的类型和大小。这就是我管理阅读的方式:
public void run(){
while(true){
try{
Headbuffer.clear();
bytes = readChannel.read(Headbuffer); //ReadableByteChannel
Headbuffer.flip();
if(bytes != -1){
int head = Headbuffer.getInt();
int size = Headbuffer.getInt();
System.out.println("received pkg: 0x" + Integer.toHexString(head)+" with size "+ size+" bytes);
switch(head){
case incoming.Pkg1: ReadWelcome(); break;
case incoming.Pkg2: ReadLoginFail();break;
case incoming.Pkg3: ReadLoginOk();break;
case incoming.Pkg4: ReadUserList();break;
case incoming.Pkg5: ReadUserData();break;
case incoming.Pkg6: ReadMessage();break;
case incoming.Pkg7: ReadTypingNotify();break;
case incoming.Pkg8: ReadListStatus();break;
case incoming.Pkg9: ChangeStatus();break;
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
在测试期间一切都很好,直到我登录我的帐户并导入我的好友列表。我向服务器发送状态请求,他将 80 个联系人中的大约 10 个发回给我。所以我想出了这样的事情:
public synchronized void readInStatus(ByteBuffer headBuffer){
byteArray.add(headBuffer); //Store every buffer in ArrayList
int buddies = MainController.controler.getContacts().getSize();
while(buddies>0){
readStuff();
readDescription();
--buddies;
}
}
并且每个 readStuff() 和 readDescription() 都在检查缓冲区中剩余字节的每个参数大小:
if(byteArray.get(current).remaining() >= 4){
uin = byteArray.get(current).getInt();
}else{
byteArray.add(Receiver.receiver.read());
current = current +1;
uin = byteArray.get(current).getInt();
}
并且 Receiver.receiver.read() 是:
public ByteBuffer read(){
try {
ByteBuffer bb = ByteBuffer.allocate(40000);
bb.order(ByteOrder.LITTLE_ENDIAN);
bytes = readChannel.read(bb);
bb.flip();
return bb;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
所以应用程序被午餐,记录,然后发送联系人。服务器将我的列表中的一部分发回给我。但是在readInStatus(ByteBuffer headBuffer)方法中,我尝试强制列表的其余部分。现在有趣的部分 - 一段时间后它到达Receiver.receiver.read()并且在bytes = readChannel.read(bb)上它只是停止了,我不知道为什么,即使经过一段时间也没有错误没有什么,我出去了的想法。我整整一周都在与解决方案作斗争,但我没有得到任何解决方案。我将不胜感激任何建议。谢谢。
感谢您的回复。是的,我正在使用阻塞 SocketChannel,我尝试了非阻塞,但它变得疯狂并且失控,所以我跳过了这个想法。关于我期望的字节 - 这有点奇怪,因为它只给了我一次大小,但它的第一部分的大小不是整个包,其他部分根本不包含标题字节。我无法预测它会有多少字节,原因是 - 容量为 255 字节的描述。这正是我在以下位置创建变量好友的原因:public synchronized void readInStatus(ByteBuffer headBuffer)
这基本上是我的好友列表的长度,在读取每个字段之前,我正在检查是否还有足够的字节,如果没有的话,我会read(). 但是描述之前的最后一个字段是带有传入描述长度的整数。但在完成某些处理之前,无法确定包裹的长度。@robert 你认为我应该在那种情况下再次尝试切换到非阻塞 SocketChannel 吗?