-4

这是代码:

System.out.println("[Server] Handshake Recieved");

String fdata = new String(p.getData());
String[] data = fdata.split(";");

System.out.println(fdata);
System.out.println(data.length);
System.out.println(data[0]);

p 是我创建的 Packet 类的名称。getData() 返回一个字节数组,我可以确认它总是正确返回。

当此代码使用 data[0] 运行时,这是控制台输出:

CID;0;Username;Dummy
4
CID

但是当我使用 data[1] 运行它时,会发生以下情况:

<blank>
1
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 1
    at server.S_GameLoop.parseData(S_GameLoop.java:122)
    at server.S_GameLoop.Update(S_GameLoop.java:87)
    at server.S_GameLoop.Running(S_GameLoop.java:66)
    at server.S_GameLoop.run(S_GameLoop.java:157)
    at java.lang.Thread.run(Thread.java:724)

我不知道为什么会这样。也许你们中的一个人知道答案?

编辑:这是包含有问题的代码的函数:

private void parseData(Packet p, DatagramPacket recievePacket) throws IOException, MethodNotOverridenException {
    switch (p.getTagAsString()) {
    case "LGN_RQS":
        System.out.println("[Server] Login Request Recieved");
        //Login was accepted
        //Create a Client ref, and add it to the vector
        S_Client newClient = new S_Client(recievePacket.getAddress(), recievePacket.getPort());
        ClientList.add(newClient);

        //Create a player and add it to Entity list
        Player newPlayer = new Player(IDGenerator.getAndIncrement(), ClientList.indexOf(newClient));
        EntityMap.put(newPlayer.getEntID(), newPlayer);
        System.out.println("[Server] Created new Player with EID " + newPlayer.getEntID() + " and CID " + newPlayer.getCID());
        //Send reply to Client that is logging in
        sendData(new Packet((byte)2, "LGN_ACP".toCharArray(), ("CID;" + ClientList.indexOf(newClient) + ";EID;" + newPlayer.getEntID()).getBytes()).getBytes(), newClient.getIp(), newClient.getPort());
        //New Entity was created
        sendData(newPlayer.onCreate(this));
    case "HND_SHK":
        System.out.println("[Server] Handshake Recieved");

        String fdata = new String(p.getData());
        String[] data = fdata.split(";");

        System.out.println(p.getData()); //[B@170ad4d5
        System.out.println(fdata);
        System.out.println(data.length);
        System.out.println(data[0]);

        /*S_Client c = ClientList.get(Integer.parseInt(data[1]));
        c.setUsername(data[3]);
        System.out.println("[Server] Set Client " + data[1] + "'s user to " + data[3]); */
    }
}

这是 Packet.java:

public class Packet {
private byte ID;
private char[] Tag;
private byte[] Data;

public Packet(byte ID, char Tag[]) {
    this.ID = ID;
    if(Tag.length <= 7)
        this.Tag = Tag;
    else
        throw new IllegalArgumentException("Tag must be at most 7 characters long");
    this.Data = new byte[1];
}

public Packet(byte ID, char Tag[], byte[] Data) {
    this.ID = ID;
    if(Tag.length <= 7)
        this.Tag = Tag;
    else
        throw new IllegalArgumentException("Tag must be at most 7 characters long");
    this.Data = Data;
}

/*
 * Returns the packet ID
 */
public byte getID() {
    return ID;
}

/*
 * Return's the packet TAG
 */
public char[] getTag() {
    return Tag;
}

public String getTagAsString() {
    return new String(Tag);
}

public byte[] getData() {
    return Data;
}

public byte[] getBytes() {
    byte[] c = {ID};
    return concat(c, concat(new String(Tag).getBytes(), Data));
}

public byte[] concat(byte[] A, byte[] B) {
       int aLen = A.length;
       int bLen = B.length;
       byte[] C= new byte[aLen+bLen];
       System.arraycopy(A, 0, C, 0, aLen);
       System.arraycopy(B, 0, C, aLen, bLen);
       return C;
}

}

第二次编辑

一点澄清。我运行该程序两次。一次使用 data[0],一次使用 data[1]。每次我运行它。它们都产生完全相同的单个结果。data[0] 将始终返回

CID;0;Username;Dummy
4
CID

哪个是对的。但是用 data[1] 换出 data[0] 总是会返回

**<blank>
1**
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 1
    at server.S_GameLoop.parseData(S_GameLoop.java:122)
    at server.S_GameLoop.Update(S_GameLoop.java:87)
    at server.S_GameLoop.Running(S_GameLoop.java:66)
    at server.S_GameLoop.run(S_GameLoop.java:157)
    at java.lang.Thread.run(Thread.java:724)

最终编辑 如果有人以某种方式遇到这个问题。问题原来是我忘记添加break;我的 switch 语句。

4

3 回答 3

3

非常仔细地查看您的第二个日志输出。在程序的第二次运行中,fdata 字符串为空,因此日志第一行是<blank>. 当你用';'标记一个空白字符串时,你会得到一个标记,也是一个空字符串。因此,日志的第 2 行是 1(令牌数组中有 1 个元素)。然后您尝试在索引 1 处索引令牌数组(访问数组的第二个元素);索引 0 处只有一个元素,因为数组的长度为 1。所以正如异常所说,您的索引超出范围。

看起来你的程序中真正的错误是 p.getData() 有时会返回一个空字符串。这表明您“确认 [数据包] 始终正确返回”的逻辑存在错误。

于 2013-06-20T21:32:54.390 回答
2

这很明显。您的不同测试确实使用不同的数据,从p.getData().

在第一次测试中,您的方法p.getData()返回了一个可以处理的良好字符串。第二个测试,你得到一个空字符串(大小为 0),这不是你所期望的。因此,请查看您提供的代码之外的内容,并搜索p.getData()返回不同内容的原因。

于 2013-06-20T21:33:15.507 回答
-1

您的数组只有一个元素,很可能是因为 split 删除了尾随的空字符串(如果有)。array[1]尝试访问不存在的第二个元素。

于 2013-06-20T21:24:37.167 回答