Я работаю над Instant Messenger, используя Java 1.6.IM использует многопоточность - основной поток, получение и пинг.Для связи по 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();
}
}
}
И во время тестов все было в порядке, пока я не вошел в свой аккаунт и не импортировал список друзей.Я отправляю запрос на сервер о статусах, и он отправляет мне обратно около 10 из 80 контактов.Итак, я придумал что-то вроде этого:
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 байтов.Именно поэтому я создал переменную buddies in: public synchronized void readInStatus(ByteBuffer headBuffer)
, которая в основном равна длине моего списка друзей, и перед чтением каждого поля я проверяю, достаточно ли осталось байтов, если его нет, я делаю чтение () .Но последнее поле перед описанием является целым с длиной входящего описания.Но невозможно определить, насколько длинным будет пакет, пока не будет выполнена некоторая обработка.@ Роберт, как ты думаешь, я должен попытаться снова переключиться на неблокирующий SocketChannel в этой ситуации?