我正在用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。
我的问题:有没有更好的方法来实现这个“发现”系统? 我知道这只能在本地网络中工作,是否可以使用本地服务器在“外部”扩展发现?
答案 0 :(得分:1)
除非你想设置一些可以将玩家与服务器连接起来的已知代理(或者给他们一个服务器列表),否则你可能会失败。正如您所发现的那样,大多数交换机通常不会将多播和广播发送到WAN(并且绝对不能通过Internet)。
如果您设置已知服务器/代理的问题是您有家庭连接而且是动态IP,我建议您查看动态DNS。有许多提供商可以让您在他们的系统上设置一个子域,当您的IP发生变化时,该子域会自动更改为指向您的IP。