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

SteamNetworkingSockets无法建立连接问题排查(C#、Steamworks.NET、MonoGame)

SteamNetworkingSockets无法建立P2P连接问题排查与修复建议

当前实现与问题场景

我用C#、Steamworks.NET和MonoGame开发时,遇到SteamNetworkingSockets无法建立连接的问题,具体实现如下:

  • 两台设备每帧(60fps锁定)调用回调:
public void Update()
{
     SteamAPI.RunCallbacks();
}
  • 程序启动时初始化中继:
SteamNetworkingUtils.InitRelayNetworkAccess();
  • 点击按钮创建监听套接字:
listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, 0, null);
  • 点击按钮发起跨设备连接:
SteamNetworkingIdentity identityRemote = new SteamNetworkingIdentity();
if (SteamUser.GetSteamID() == new CSteamID("mySteamID"))
     identityRemote.SetSteamID64("anotherSteamID");
else
     identityRemote.SetSteamID64("mySteamID");

connectionSocket = SteamNetworkingSockets.ConnectP2P(ref identityRemote, 0, 0, null);
  • 连接处理逻辑:检测到连接状态为k_ESteamNetworkingConnectionState_Connecting时重复调用接受连接:
if (connectionState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connecting)
{ 
     SteamNetworkingSockets.AcceptConnection(connectionSocket);
}

问题现象

双方始终无法建立连接,一段时间后连接状态变为k_ESteamNetworkingConnectionState_ProblemDetectedLocally(超时)。已连续3天排查,查阅Steamworks文档、参考示例项目、尝试Facepunch.Steamworks(因习惯问题未适应),仍未解决。


排查与修复建议

1. 修正连接接受逻辑的触发时机

AcceptConnection不能在Connecting状态重复调用,正确的做法是仅在收到SteamNetConnectionStatusChangedCallback_t回调且状态为k_ESteamNetworkingConnectionState_RequestingConnection时调用一次,重复调用会干扰连接流程:

private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t callback)
{
    var state = callback.m_info.m_eState;
    var connection = callback.m_hConn;

    switch (state)
    {
        case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_RequestingConnection:
            SteamNetworkingSockets.AcceptConnection(connection);
            break;
        case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected:
            // 连接成功后的业务逻辑
            break;
        case ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
            // 打印错误详情用于排查
            Debug.WriteLine($"连接错误原因: {callback.m_info.m_szDebug}");
            break;
    }
}

2. 修复SteamID的使用方式

当前代码中用字符串包裹SteamID的写法会导致解析错误,必须传入纯数字的64位SteamID:

// 错误写法
new CSteamID("mySteamID");
// 正确写法(示例ID为12345678901234567)
new CSteamID(12345678901234567);
// SetSteamID64同理,直接传数字
identityRemote.SetSteamID64(12345678901234567);

同时要确保两台设备登录的Steam账号与目标SteamID完全匹配。

3. 验证中继网络与初始化顺序

  • 确保SteamNetworkingUtils.InitRelayNetworkAccess()在SteamAPI.Init()成功返回true之后调用
  • 调用SteamNetworkingUtils.GetRelayNetworkStatus()获取中继状态,打印返回值确认是否正常连接到Steam中继服务器
  • 检查Steam后台游戏设置:确保启用P2P功能,测试账号已添加为Steam开发者测试用户

4. 绑定监听套接字的回调

创建监听套接字后,必须绑定连接状态变化的回调,否则无法收到对方的连接请求:

listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, 0, null);
// 绑定回调以接收连接状态变更通知
Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);

5. 避免双向主动连接冲突

不要在检测到连接请求后发起反向连接,这会导致双方同时发起连接造成冲突。正确流程是:

  • 单一方作为监听端创建套接字等待请求
  • 另一方作为客户端主动调用ConnectP2P发起连接
  • 监听端收到RequestingConnection状态时调用AcceptConnection

6. 打印详细错误日志

当连接状态变为ProblemDetectedLocally时,打印callback.m_info.m_szDebug和callback.m_info.m_eEndReason,这些信息会直接给出超时的具体原因(如中继不可达、防火墙拦截、SteamID错误等)。

内容的提问来源于stack exchange,提问作者Ailtairon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:30:27