只有最后一个客户端才能获取数据

时间:2016-04-30 18:16:34

标签: java tcp server client multiplayer

我有一个小问题。我是多人游戏编程新手。我的问题是,只发送一个数据包会被发送到最后一个客户端。它可以轻松支持2名玩家,但是3名玩家并不能完全发挥作用。登录和断开数据包有效,但移动数据包无效。你能告诉我我失踪或需要删除的东西吗?

客户端:

public class Client extends Thread{
private InetAddress ip;
private DatagramSocket dp;

public Client(String ia) {
    try {
    dp = new DatagramSocket();
    ip = InetAddress.getByName(ia);
    } catch (SocketException | UnknownHostException e) {
    e.printStackTrace();
    }
}

@Override
public void run() {
    while (true) {
        byte[] rdata = new byte[1024];
        DatagramPacket dg = new DatagramPacket(rdata, rdata.length);
        try {
            dp.receive(dg);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        byte[] data = dg.getData();
        String msg = new String(data).trim();
        switch (Packet.find(msg.substring(0, 2))) {
            default:
            case INVALID:
                break;
            case LOGIN:
                Login00 l = new Login00(data);
                if (getPlayer(l.getUser()) == null) {
                Main.visible.add(new MPlayer(100, 100, l.getUser(), dg.getAddress(), dg.getPort(), false));
                System.out.println("("+dg.getAddress().getHostAddress()+":"+dg.getPort()+") > " + msg.substring(2) + " has joined!");
                }
                break;
            case DISCONNECT:
                Dis01 d = new Dis01(data);
                Main.visible.remove(getPlayer(d.getUser()));
     System.out.println(("+dg.getAddress().getHostAddress()+":"+dg.getPort()+") > " + d.getUser() + " has left!");
                break;
            case MOVE:
                Move02 m = new Move02(data);
                handleMove(m);
                break;
        }
    }
}

public void sendData(byte[] data) {
    try {
    DatagramPacket dg = new DatagramPacket(data, data.length, ip, 1111);
    dp.send(dg);
    } catch (Exception ex) {
        //ex.printStackTrace();
    }
}



public MPlayer getPlayer(String u) {
    for (Player p : Main.visible) {
        if (p.user.equals(u)) {
            return (MPlayer) p;
        }
    }
    return null;
}

public int getPlayerId(String u) {
    int dex = 0;
    for (Player p : Main.visible) {
        if (p.user.equals(u)) {
            break;
        }
        dex++;
    }
    return dex;
}

private void handleMove(Move02 m) {
    int dex = getPlayerId(m.getUser());
    Main.visible.get(dex).moveTo(m.getX(), m.getY(), m.getUser());
}
}

服务器:

public class Server extends Thread{
private DatagramSocket dp;
List<MPlayer> cplayers = new ArrayList<>();

public Server() {
    try {
    dp = new DatagramSocket(1111);
    } catch (SocketException e) {
    e.printStackTrace();
    }
}

@Override
public void run() {
    while (true) {
        byte[] rdata = new byte[1024];
        DatagramPacket dg = new DatagramPacket(rdata, rdata.length);
        try {
            dp.receive(dg);
        } catch (IOException ex) {
        }
        pp(dg.getData(), dg.getAddress(), dg.getPort());
    }
}

public void sendData(byte[] data, InetAddress i, int port) {
    try {
        DatagramPacket dg = new DatagramPacket(data, data.length, i, port);
        dp.send(dg);
    } catch (Exception ex) {
    }
}

public void sendDataAll(byte[] data) {
    for (MPlayer p : cplayers) {
        sendData(data, p.ip, p.port);
    }
}

private void pp(byte[] data, InetAddress address, int port) {
    String msg = new String(data).trim();
    types t = Packet.find(Integer.parseInt(msg.substring(0, 2)));
    Packet pp;
    switch (t) {
        default:
        case INVALID:
            break;
        case LOGIN:
            pp = new Login00(data);
            System.out.println("("+address.getHostAddress()+":"+port+") > " + ((Login00) pp).getUser() + " has joined!");
            MPlayer pl = new MPlayer(100, 100, ((Login00) pp).getUser(), address, port, false);
            addPlayer(pl, (Login00) pp);
            break;
        case DISCONNECT:
            pp = new Dis01(data);
            System.out.println("("+address.getHostAddress()+":"+port+") > " + ((Dis01) pp).getUser() + " has left!");
            removePlayer((Dis01) pp);
            break;
        case MOVE:
            pp = new Move02(data);
            handleMove((Move02) pp);
            break;
    }
}

public void addPlayer(MPlayer pl, Login00 l) {
    boolean ac = false;
    for (MPlayer p : cplayers) {
        p.ip = pl.ip;
        p.port = pl.port;
        if (Main.username.equalsIgnoreCase(l.getUser())) {
            ac = true;
        } else {
            sendDataAll(l.getData());
            Login00 ll = new Login00(p.user);
            sendData(ll.getData(), p.ip, p.port);
        }
    }
    if (true) {
        cplayers.add(pl);
        Main.visible.add(pl);
    } 

}

public void removePlayer(Dis01 dis) {
    Main.visible.remove(getPlayer(dis.getUser()));
    cplayers.remove(getPlayer(dis.getUser()));
    dis.write(this);
}

public MPlayer getPlayer(String u) {
    for (MPlayer p : cplayers) {
        if (p.user.equals(u)) {
            return p;
        }
    }
    return null;
}

public int getPlayerId(String u) {
    int dex = 0;
    for (Player p : Main.visible) {
        if (p.user.equals(u)) {
            break;
        }
        dex++;
    }
    return dex;
}

public void handleMove(Move02 m) {
        Integer dex = getPlayerId(m.getUser());
        Main.visible.get(dex).moveTo(m.getX(), m.getY(), m.getUser());
        m.write(this);
}
}

编辑:所以我发现我需要将Server类中的addPlayer方法更改为:

public void addPlayer(MPlayer pl, Login00 l) {
    cplayers.add(pl);
    Main.visible.add(pl);
    for (MPlayer p : cplayers) {
        sendDataAll(l.getData());
        Login00 ll = new Login00(p.user);
        sendDataAll(ll.getData());
    }
}

1 个答案:

答案 0 :(得分:1)

添加播放器时,会覆盖所有现有播放器的IP和端口

// Server code
public void addPlayer(MPlayer pl, Login00 l) {
    boolean ac = false;
    for (MPlayer p : cplayers) {
        // At this point, you overwrite all existing player data
        p.ip = pl.ip; // overwrites existing player
        p.port = pl.port; // overwrites existing player
        if (Main.username.equalsIgnoreCase(l.getUser())) {
            ac = true;
        } else {
            sendDataAll(l.getData());
            Login00 ll = new Login00(p.user);
            sendData(ll.getData(), p.ip, p.port);
        }
    }
}