私はJava 1.6を使用してインスタントメッセンジャーに取り組んでいます。IM は、マルチスレッド (メイン スレッド、受信、および ping) を使用します。TCP/IP 通信には SocketChannel を使用しました。また、サーバーから大きなパッケージを受信する際に問題があるようです。サーバーは1つではなく2つのパッケージを送信し、そこから問題が始まります。最初の 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()に到達し、バイト = readChannel.read(bb)で停止し、理由がわかりません。しばらくしてもエラーはなく、何もありません。アイデアの。私はこの一週間ずっと戦っていますが、解決策に近づくことはできません。提案をいただければ幸いです。ありがとう。
返信ありがとうございます。はい、ブロッキング SocketChannel を使用しています。ノンブロッキングを試しましたが、暴走して制御不能になったため、アイデアをスキップしました。私が期待するバイトについて-これはちょっと奇妙です。なぜなら、サイズはヘッドで1回だけですが、パッケージ全体ではなく最初の部分のサイズであり、他の部分にはヘッダーバイトがまったく含まれていないからです。それが何バイトになるかは予測できません。その理由は、容量が 255 バイトの記述です。これがまさに私が変数バディを作成した理由です:これpublic synchronized void readInStatus(ByteBuffer headBuffer)
は基本的にバディリストの長さであり、各フィールドを読み取る前に、十分なバイトが残っているかどうかを確認します。そうでない場合はread()を実行します. ただし、説明の前の最後のフィールドは、着信説明の長さを持つ整数です。ただし、何らかの処理が完了するまで、パッケージの長さを判断することは不可能です。@robertその状況でノンブロッキングSocketChannelにもう一度切り替えてみるべきだと思いますか?