0

首先我使用的是 NetBeans IDE。有一个客户端,它的一个线程从服务器接收消息并将它们放入 Vector 中,另一个线程处理它们。MessageListener 和 MessageHandler 是那些。所以问题是它收到的第一条消息运行良好,但是对于下一条消息,当它调用方法 byte[] getFirstMessage() 时,它返回值为 0 的字节。

在我看来,问题出在 Vector addElement 方法上,它将第二条消息添加到索引 1 而不是 0,尽管它在将数据传递给 MessageHandler 或我使用时删除了 vector 的第一个元素的内容某些方法中的局部变量。PS它应该是消息队列。

消息监听器.java

package org.rebirth;

import java.io.*;
import java.util.*;

public class MessageListener implements Runnable{

Vector v; 
int size = 0;
Connections con;
byte[] buffer = new byte[100000];
boolean noErrors = true;

public MessageListener(Connections con){
    v = new Vector(50,10);

    this.con = con;

    Thread thr = new Thread(this);
    thr.start();
}

public void run(){

    while(noErrors){            
        try{   

            listenForData();
            Thread.sleep(1);            
        }catch(Exception exc){
            exc.printStackTrace();  
            noErrors = false;
        }
    }
}

public void listenForData() throws IOException{


    con.fill(buffer,(byte)0);
    System.out.println("Trying to receive data");
    // InputStream                                                             
    con.in.read(buffer);
    System.out.println("Data received id "+con.ReadInt3Bytes(buffer,1));
    v.addElement(buffer);
    size++;

    if(v.isEmpty()){
        System.out.println("empty");
    }


}

public byte[] getFirstMessage(){
    if(v.size()>0){
        byte[] data = (byte[]) v.firstElement();
        v.removeElementAt(0); 
        size--;

        System.out.println("first byte element "+(int)data[0]);

        return data;
    }
    return null;
}

}

消息处理程序.java

 package org.rebirth;

 import java.util.*;
 import javax.microedition.lcdui.game.*;

public class MessageHandler implements Runnable{

Vector v;
MessageListener lst;
Connections con;
int vienas = 1;

public MessageHandler(Vector v,MessageListener lst){
    this.v = v;
    this.lst = lst;
    this.con = lst.con;

    Thread thr = new Thread(this);
    thr.start();
}


public void run(){
    while(true){
        try{

            if(!v.isEmpty()){                    
                handleMessages();

            }
            Thread.sleep(10);            
        }catch(Exception exc){}
    }
}

public void handleMessages(){
   // vectordsfds

    int id;

    byte [] gotByte = lst.getFirstMessage();        
    id=con.ReadInt3Bytes(gotByte,1);       
    System.out.println("handler id: "+id);

    // call a method to handle received message;
    handleMessage(id,gotByte);          
}

public void handleMessage(int id,byte[] gotByte){
    switch(id){            

        case 62:
            // GameServerList

            con.serverNumber = (int)gotByte[4];
            System.out.println("Servers "+con.serverNumber);        

                    int nri = 6;
                    for(int i=0;i<con.serverNumber;i++){

                        nameLength = (int)gotByte[nri];
                        nri+=1;
                        con.serverName[i] = new String(gotByte, nri, nameLength);
                        nri+=nameLength;
                        int ipLength = (int)gotByte[nri];
                        nri+=1;
                        con.serverIp[i] = new String(gotByte, nri, ipLength);
                        nri+=ipLength;
                        con.online[i] = con.ReadInt3Bytes(gotByte,nri);
                        nri+=3;
                        con.maxOnline[i] = con.ReadInt3Bytes(gotByte,nri);

                        System.out.println("Server name " +con.serverName[i]);
                        System.out.println("ip "+con.serverIp[i]);
                        System.out.println("online "+con.online[i]);
                        System.out.println("max online "+con.maxOnline[i]);
                        nri+=4;
                    }

            break;

        case 64:
            //GameVersion


            int success = (int)gotByte[4];


            if(success == 1){
                con.version=true;
                System.out.println("Version match!");

        }else{
                System.out.println("version does not match");
                System.out.println(success);
            }

        break;




    }
}


}

编辑 2:我在读取数据之前添加了一个语句 InputStream 类 available() 方法。

4

2 回答 2

0

准确理解您的代码发生了什么并不是那么简单。但是方法listenForData()确实将由零填充的字节数组添加到您的向量中:

con.fill(buffer,(byte)0); 
......
v.addElement(buffer);

所以,虽然你是新来的,我想欢迎你并祝你成功,但我想问你一些问题。

  1. 你知道 J2ME 已经过时了吗?如果您想对移动设备进行编程,请查看 Android OS。
  2. 您真的认为 JDK 类(如Vector)包含您可以通过编写您的第一个程序发现的错误吗?
  3. 你听说过调试器吗?尝试调试您的代码以了解它为什么不起作用。
  4. 如果您想提出问题并获得好的答案,请查看SSCCE

祝你好运。

于 2013-08-13T05:53:24.893 回答
0

我很惊讶它有时甚至可以工作。如果我正确阅读了源代码,那么您对所有传入消息使用相同的缓冲区实例。Vector.addElement 不会创建缓冲区的副本,它只是保存作为参数传递的引用,因此在 while(noErrors) 循环中运行的 listenForData 将在再次运行时将(唯一的)缓冲区清除为零。并且当它再次运行时取决于线程的调度方式,因此有时消息侦听器会获取包含真实数据的缓冲区,有时会获取零。

此外,我不确定 CLDC Vector 是否与 J2SE 不同,是同步的。所以我认为向量访问应该是同步的。而且我不确定您使用的是什么类型的连接,但是从流中读取字节而不检查返回值并且不知道应该读取多少字节似乎有点不可靠的代码......

编辑:通过“知道你应该读取多少字节”我并不是说使用 available() 函数,它可能会为许多类型的流返回 0。当 read() 返回时,它可能(并且经常这样做)读取的字节数少于请求的字节数,因此您永远无法确定缓冲区中是否有足够的数据可以使用,除非您知道您正在等待多少数据并继续阅读直到你拥有它们。我认为您应该定义一个协议,如果它适合您的需要,它可以像固定大小的消息一样简单。

于 2013-08-15T09:32:29.460 回答