Socket桌面象棋应用实现可用游戏房间列表的最优方案咨询
最简实现方案推荐
优先推荐局域网UDP广播探测方案,完全不需要第三方云服务,和你现有代码兼容性极高,改造成本不到百行代码,适合绝大多数本地好友对战的场景;如果需要支持跨网对战,再加一个极简的公共注册服务即可。
方案1:局域网UDP广播探测(零成本首选)
实现逻辑
- 房主创建房间启动
GameServer时,额外启动一个固定端口的UDP监听线程,收到客户端的探测请求就返回当前房间的IP、房主名、房间状态等信息 - 玩家点击「查找房间」按钮时,客户端向局域网广播地址
255.255.255.255发送探测包,收集3秒内所有返回的房间信息,渲染成列表供用户选择 - 用户选中对应房间后,直接用返回的IP调用你原有
Connect方法即可,对战逻辑完全不用改动
代码实现
房主端新增UDP监听逻辑
在GameServer启动时同步启动该线程即可:
import java.net.*; import java.nio.charset.StandardCharsets; public class RoomBroadcastListener implements Runnable { private static final int BROADCAST_PORT = 49999; private final String roomOwner; public RoomBroadcastListener(String roomOwner) { this.roomOwner = roomOwner; } @Override public void run() { try (DatagramSocket socket = new DatagramSocket(BROADCAST_PORT)) { byte[] buffer = new byte[1024]; while (!Thread.currentThread().isInterrupted()) { DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length); socket.receive(receivePacket); // 收到探测请求后返回房间信息 String localIp = InetAddress.getLocalHost().getHostAddress(); String respContent = localIp + "," + roomOwner + ",等待加入"; byte[] respBytes = respContent.getBytes(StandardCharsets.UTF_8); DatagramPacket respPacket = new DatagramPacket(respBytes, respBytes.length, receivePacket.getAddress(), receivePacket.getPort()); socket.send(respPacket); } } catch (Exception e) { e.printStackTrace(); } } }
修改GameServer构造方法启动监听:
public GameServer(String roomOwner){ // 启动UDP房间广播监听 new Thread(new RoomBroadcastListener(roomOwner)).start(); }
客户端新增探测逻辑
用户点击「查找房间」时执行该逻辑,将返回的列表渲染到JavaFX的ListView组件即可:
import java.net.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; // 房间信息实体类,你可以自行扩展字段 class RoomInfo { public String ip; public String owner; public String status; public RoomInfo(String ip, String owner, String status) { this.ip = ip; this.owner = owner; this.status = status; } } public List<RoomInfo> scanRooms() { List<RoomInfo> roomList = new ArrayList<>(); try (DatagramSocket socket = new DatagramSocket()) { socket.setSoTimeout(3000); // 发送探测广播 byte[] probeBytes = "scan_room".getBytes(StandardCharsets.UTF_8); DatagramPacket probePacket = new DatagramPacket(probeBytes, probeBytes.length, InetAddress.getByName("255.255.255.255"), 49999); socket.send(probePacket); // 收集3秒内返回的所有房间信息 byte[] buffer = new byte[1024]; long startTime = System.currentTimeMillis(); while (System.currentTimeMillis() - startTime < 3000) { try { DatagramPacket respPacket = new DatagramPacket(buffer, buffer.length); socket.receive(respPacket); String[] resp = new String(respPacket.getData(), 0, respPacket.getLength()).split(","); roomList.add(new RoomInfo(resp[0], resp[1], resp[2])); } catch (SocketTimeoutException e) { break; } } } catch (Exception e) { e.printStackTrace(); } return roomList; }
方案2:公网对战方案(仅需额外轻量注册服务)
如果需要支持跨网对战,只需要搭一个极简的公共接口服务即可,比Firestore轻量很多:
- 服务端只需要3个接口:上报房间信息、拉取房间列表、删除房间信息,用SpringBoot几十行代码就能写完,1核2G的低配服务器就能承载上万次请求
- 房主创建房间后上报自己的公网IP、房间信息到服务端,客户端拉取列表选择后直接连接原有对战端口即可
- 注意需要房主做端口映射或者开启UPnP,否则公网无法直接访问内网的
ServerSocket
内容的提问来源于stack exchange,提问作者Mizsi
相关产品推荐
相关产品推荐

