首先,我使用的是NetBeans IDE。有一个客户端,它的一个线程从服务器接收消息并将它们放在Vector中,另一个线程处理它们。 MessageListener和MessageHandler就是那些。所以问题是它收到它的第一条消息运行良好,但是当它调用方法byte [] getFirstMessage()时,它返回下一条消息,它返回值为0的字节。
在我的观点中,问题是使用Vector addElement方法将第二条消息添加到索引1而不是0,尽管它会在将数据传递给MessageHandler时删除vector的第一个元素的内容,或者我在某些方法中使用局部变量。 P.S它应该是消息队列。
MessageListener.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;
}
}
Messagehandler.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()方法。
答案 0 :(得分:0)
理解你的代码究竟发生了什么并不是那么简单。但是,方法listenForData()
确实将由零填充的字节数组添加到向量中:
con.fill(buffer,(byte)0);
......
v.addElement(buffer);
所以,虽然你是新来的,我想欢迎你,并祝你取得很大的成功,我想问你一些问题。
Vector
)包含您可以通过编写第一个程序发现的错误?答案 1 :(得分:0)
我甚至有时会感到惊讶。如果我正在读取源代码,则对所有传入消息使用相同的缓冲区实例。 Vector.addElement不会创建缓冲区的副本,它只保存作为param传递的引用,因此while(noErrors)循环中运行的listenForData将在它再次运行时立即清除(唯一的)缓冲区。当它再次运行depedsn如何调度线程时,所以有时消息监听器会获取具有实际数据的缓冲区,有时还会使用零。
此外,我不确定CLDC Vector是否与J2SE不同,是同步的。所以我认为矢量访问应该是同步的。 而且我不确定你正在使用什么类型的连接,但是从流中读取字节而不检查返回值并且不知道你应该读取多少字节似乎有点不可靠的代码......
编辑:通过“知道你应该阅读多少字节”我并不是指使用available()函数,对于许多类型的流,它很可能返回0。当read()返回时,它可能(并且经常)读取的字节数少于请求的数量,因此您永远无法确定缓冲区中是否有足够的数据可供使用,除非您知道等待的数据量是多少并且您继续阅读直到你拥有它们。我认为你应该定义一个协议,它可以像固定大小的消息一样简单,如果它符合你的需要。