2

我正在用 Java 创建一个游戏,模拟经典的 5 张牌扑克,有 2 到 4 名玩家。大多数数据将由服务器处理,但由于我不能使用在线服务器,我的想法是允许用户通过创建本地游戏来托管游戏。

现在,我不想强​​制使用 IP 连接游戏,所以我在用户内创建了一个“发现”界面,可以看到所有可用的游戏。这是使用 UDP 协议和对一个公共组的广播研究来完成的:

(代码被简化为仅显示已执行的操作,可能无法像此处显示的那样工作)

客户

MulticastSocket socket = new MulticastSocket(6020);
InetAddress group = InetAddress.getByName("226.0.0.1");
socket.joinGroup(group);

DatagramPacket packet = new DatagramPacket(new byte[] {(byte) 0xF0}, 1, group, 6020);
socket.send(packet);

while(true) {
    buf = new byte[1];
    packet = new DatagramPacket(buf, buf.length);
    socket.receive(packet);

    if(packet.getData()[0] == 15) {
        Socket client = new Socket(packet.getAddress(), 6020);
    }
}

服务器

MulticastSocket socket = new MulticastSocket(6020);
InetAddress group = InetAddress.getByName("226.0.0.1");
socket.joinGroup(group);

// new thread listening on port 6020 TCP
ServerSocket server = new ServerSocket(6020);
new Thread(new Runnable() {

            public void run() {
                while(true) {
                    // new thread communicating with client and back listening on port 6020
                    new ServerThread(server.accept());
                }
            }
}).start();

// listening on port 6020 UDP
byte[] buf;
DatagramPacket packet;
while(true) {
    buf = new byte[1];
    packet = new DatagramPacket(buf, buf.length);
    socket.receive(packet);

    if(packet.getData()[0] == -16) {
        DatagramPacket packet = new DatagramPacket(new byte[] {(byte) 0x0F}, 1, packet.getSocketAddress());
        socket.send(packet);
    }
}

客户端在 6020 端口上发送一个 UDP 广播包。当服务器收到这个包,如果它是由一个字节 0xF0 组成的,他会向客户端发回一个字节 0x0F。每个客户端也在侦听端口 6020,当接收到由字节 0x0F 组成的数据包时,它会在端口 6020 上启动到服务器的新 TCP 连接。

我的问题:有没有更好的方法来实现这个“发现”系统?我知道这仅适用于本地网络,是否可以使用本地服务器将发现“扩展”到“外部”?

4

1 回答 1

1

除非您想建立某种可以将玩家与服务器连接起来的已知代理(或给他们一个服务器列表),否则您可能不走运。正如您所发现的,大多数交换机通常不会将多播和广播发送到 WAN(并且绝对不能穿越 Internet)。

如果您设置已知服务器/代理的问题是您有家庭连接和动态 ip,我建议您查看动态 DNS。有许多提供商允许您在他们的系统上设置一个子域,当您的 IP 更改时,该子域会自动更改为指向您的 IP。

于 2012-05-04T18:17:29.717 回答