You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:45:03