我正在使用Java 1.6的即时通讯工作。 IM使用多线程 - 主线程,接收和ping。对于TCP/IP通信,我使用SocketChannel。从服务器接收更大的包似乎有问题。服务器,而不是一个发送一些包,这就是问题开始的地方。每前8个字节是告诉什么是什么类型的包,它有多大。这是我如何管理阅读:ReadableByteChannel挂在读取(bytebuffer)
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)它只是停下来,我不知道为什么,没有错误没有什么,甚至在一些时间和Im出于想法。我整个星期都在和这场战斗搏斗,我没有得到任何解决方案。我会感谢任何建议。谢谢。
感谢您的回复。是的,我正在使用阻塞SocketChannel,我尝试了非阻塞,但它疯狂和失控,所以我跳过了这个想法。关于我期望的字节数 - 这有点奇怪,因为它的头只给我一次大小,但是它的大小不是整个包的第一部分,其他部分根本不包含头字节。我无法预测它将有多少字节,原因是 - 具有255字节容量的描述。这就是为什么我创建变量好友在:public synchronized void readInStatus(ByteBuffer headBuffer)
这基本上是我的好友列表的长度和阅读每个字段之前我检查是否有足够的剩余字节,如果它不是,我做阅读() 。但是描述之前的最后一个字段是具有传入描述长度的整数。但是不可能确定封装的时间长度,直到完成一些处理。 @robert你认为我应该再次尝试在这种情况下切换到非阻塞SocketChannel吗?
感谢您的快速回复。不过,我认为我做得很对,一切都按照它的想法进行。我在发送前检查了缓冲区的大小及其正确性。发送只需要两个变量int和byte,所以它非常简单。联系人存储在Hashtable中,我从上到下迭代。 –
问题是接收缓冲区的限制。您可以清除它,当您将其设置为“大小”大小时,请阅读,清除,然后根据大小设置缓冲区限制,然后以相同方式再次读取数据。我是BTW网络工程师。 –