Im работает с мессенджером, используя java 1.6. IM использует многопоточность - основной поток, прием и пинг. Для связи 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();
}
}
}
А во время испытаний все было хорошо, пока я не вошел в мой счет и импортировать мои френды. Я отправляю запрос на сервер для статусов, и он отправляет мне около 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) он просто останавливается, и я не знаю, почему, никаких ошибок нет ничего даже после некоторых времени и Im из идей. Im сражается с этой целую неделю и я не получаю где-нибудь около решения. Буду признателен за любые предложения. Благодарю.
Благодарим за ответ. Да, я использую блокировку SocketChannel, я пробовал не блокировать, но он одичал и вышел из-под контроля, поэтому я пропустил эту идею. О байтах, которые я ожидаю - это довольно странно, потому что он дает мне размер только один раз в голову, но его размер первой части не весь пакет, остальные части не содержат байтов заголовка вообще. Я не могу предсказать, сколько байтов это будет, причина в том, что - описания с емкостью 255 байт. Именно поэтому я создал переменную друзей в: public synchronized void readInStatus(ByteBuffer headBuffer)
wich в основном длина моего списка контактов и перед чтением каждого поля. Я проверяю, осталось ли достаточно байтов, если это не так, я делаю read() , Но последнее поле перед описанием является целым числом с длиной входящего описания. Но его невозможно определить, как долго пакет, до тех пор, пока не будет выполнена какая-либо обработка. @robert, вы думаете, я должен попробовать снова переключиться на неблокирующий SocketChannel в этой ситуации?
Спасибо за быстрый ответ. Однако я думаю, что я делаю это правильно, и все на месте, как предполагается. Я проверял размер буфера перед отправкой и его правильность. Для отправки требуется только две переменные int и byte, поэтому это довольно простая математика. Контакты хранятся в Hashtable, и я повторяю сверху вниз. –
Проблема - это предел принимающего буфера. Вы очищаете его, когда вы должны установить его размер «размер», прочитать, очистить, затем установить ограничение на буфер на основе размера, а затем снова прочитать то же самое для данных. Я инженер сети BTW. –