Steamworks 文献库
ISteamNetworkingUtils 接口
用于检查本地网络环境并对 ping 进行估测的杂项网络实用工具。

相关文档:

ISteamNetworkingUtils 的成员函数通过全局访问器函数 SteamNetworkingUtils() 调用。

初始化与状态检查

InitRelayNetworkAccess

void InitRelayNetworkAccess();
如果您知道您将会使用中继网路(比如您预期会进行 P2P 连接),调用此函数以初始化中继网络。 如果您不调用此函数,初始化将会被推迟,直到您首次看到需要访问中继网络的功能,而这会推迟首次访问。

如果之前的尝试失败,您也可以调用此函数以强制进行重试。 执行任何要求访问中继网络的操作也将会触发一次重试,因此从不严格要求调用此函数,但如果预期会访问中继网络,那么在启动程序时调用可能会有帮助。 使用 GetRelayNetworkStatus 或侦听 SteamRelayNetworkStatus_t 调用,以了解初始化何时完成。 初始化一般在几秒内完成。

注意:托管于已知数据中心的专用服务器无需调用此函数,因为这些服务器不会做出路由决定。 然而,如果专用服务器将会使用 P2P 功能,那么它将会作为“客户端”,应该调用此函数。

GetRelayNetworkStatus

ESteamNetworkingAvailability GetRelayNetworkStatus( SteamRelayNetworkStatus_t *pDetails );
获取中继网络的当前状态。

SteamRelayNetworkStatus_t 同样是回调。 每当状态变更,或 ping 测量开始或结束时,它将会在用户端和游戏服务器接口触发。

返回 SteamRelayNetworkStatus_t::m_eAvail。 如果需要更多详情,可传入一个非 NULL 值。

Ping 地点函数


我们使用部署于全球的 Valve 中继的 ping 时间来生成一个“标记”,描述互联网主机的地点。 若有两个这样的标记,我们就可以估计两个主机之间的网络延迟,而不需发送任何数据包。 估计结果是通过基于 Valve 网络而找到的最佳线路而得出的。 如果您在使用 Valve 网络来承载流量,那么这正是您需要的 ping。 否则,ping 时间仍将是合理的估计。

这对于在对战匹配中选择可选的对等端来说及其有用!

标记还可以转换为字符串,因此可以传输。 我们有单独的库供您在自己的后端使用,以操控这些对象。 (见 steamdatagramrelay

GetLocalPingLocation

float GetLocalPingLocation( SteamNetworkPingLocation_t &result );

返回当前主机的地点信息。 返回数据的大概存在时间,以秒计,如果无可用数据,则返回 -1。

初始化对中继网络的访问需要几秒种的时间。 如果在调用 InitializeRelayNetworkAccess 后立刻调用此函数,可能还没有可用数据。

它总是返回当前最新的信息,即便处于重新计算 ping 时间的过程中也是如此。

EstimatePingTimeBetweenTwoLocations

int EstimatePingTimeBetweenTwoLocations( const SteamNetworkPingLocation_t &location1, const SteamNetworkPingLocation_t &location2 );

估计两个随机地点之间的往返延迟,以毫秒计。 此为保守估计,基于通过中继网络的线路而得出。 对于最基本的中继连接而言,此 ping 时间将十分准确,因为它基于的是可能真正使用的路线。

如果使用了直接的 IP 线路(可能是通过 NAT 遍历),那么该线路会是不同的线路,且可能会有更佳的 ping 时间。 但也有可能是稍差一些的 ping 时间! 标准 IP 路由常常不能带来理想结果!

但即便如此,使用该方法获取的估计值也是 ping 时间的合理上限。 (此外它还有立即返回和不发送任何数据包的优点。)

在少数几种情况下我们可能无法估计路线。 如果是这样,会返回一个负值。 k_nSteamNetworkingPing_Failed 表明原因是网络障碍 (ping 失败等)。如果出于某种原因,我们当前无法回答问题,则返回 k_nSteamNetworkingPing_Unknown。

需要能够在后端/对战匹配服务器上进行此操作吗? 如果是,则“游戏协调程序”库正是您需要的。 参见 steamdatagramrelay,进一步了解如何获取游戏协调程序 SDK。

EstimatePingTimeFromLocalHost

int EstimatePingTimeFromLocalHost( const SteamNetworkPingLocation_t &remoteLocation );
和 EstimatePingTime 相同,但假定一个地点是本地主机。 此函数稍快,尤其是当需要循环计算多个此类函数以找到最快的那个时。

在极少的情况下,此函数返回的结果会稍不同于将 GetLocalPingLocation 与 EstimatePingTimeBetweenTwoLocations 结合的结果。 这是因为此函数会视使用的路线而采用稍微更复杂的一组信息。

ConvertPingLocationToString

void ConvertPingLocationToString( const SteamNetworkPingLocation_t &location, char *pszBuf, int cchBufSize );
将 ping 地点转化为适于网络传送的文本格式。 这种格式紧凑且便于阅读。 但它还会根据情况更改,因此请不要自行解析。 您的缓冲区必须为至少 k_cchMaxSteamNetworkingPingLocationString 字节。

ParsePingLocationString

bool ParsePingLocationString( const char *pszString, SteamNetworkPingLocation_t &result );
解析回 SteamNetworkPingLocation_t 字符串。 如果我们无法理解该字符串,则返回“false”。

Ping 测量状态函数


使用中继网络要求测量延迟时间。 除了在应用程序启动时调用 InitializeRelayNetworkAccess外(在您知道您将会需要访问中继网络以发送流量或只是估计 ping 时),延迟时间的采集过程将会自动发生。 这些函数允许对这一过程有更多一点的控制。

CheckPingDataUpToDate

bool CheckPingDataUpToDate( float flMaxAgeSeconds );
检查是否有近期的 ping 数据可用,如果 ping 数据太旧,则刷新。

请仅在您确实需要强制数据立即刷新时才调用此函数。 (比如为了响应一个具体的用户输入而刷新此信息。) 请勿为了“以防万一”或在每次连接前调用此函数。那样会导致无谓地发送额外流量。 库会按需自动刷新该信息。

如果已有近期数据可用,则会返回“true”。

如果没有近期数据可用,则会返回“false”。 在这种情况下,ping 测量就算没有处于活跃状态,也已经启动。 (您无法重启已经在进行中的测量。)

IsPingMeasurementInProgress

bool IsPingMeasurementInProgress();
如果我们正在进行 ping 测量以更新我们的 ping 地点或选择最佳路径,则返回 true。 Ping 测量通常需要几秒钟,最长可能达到 10 秒。

Valve 网络拓扑函数


Valve 接入点(“POP”)列表及其 ping 时间。 如果您在使用我们的托管服务,或仅需要测量与包含我们的中继的云数据中心之间的延迟,此函数可能会有帮助。

GetPingToDataCenter

int GetPingToDataCenter( SteamNetworkingPOPID popID, SteamNetworkingPOPID *pViaRelayPoP );
提取从该主机到指定数据中心间的可用最佳中继路径的 ping 时间。

GetDirectPingToPOP

int GetDirectPingToPOP( SteamNetworkingPOPID popID );
获取接入点的中继的*直接* ping 时间。

GetPOPCount

int GetPOPCount();
获取配置中网络存在点的数量

GetPOPList

int GetPOPList( SteamNetworkingPOPID *list, int nListSz );
获取所有 POP ID 的列表。 返回填入您列表的条目的数量。

配置函数


控制网络选项。 见 ESteamNetworkingConfigValue,了解每个选项的描述。

SetConfigValue

bool SetConfigValue( ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, intptr_t scopeObj, ESteamNetworkingConfigDataType eDataType, const void *pArg );


设置一个配置值。
  • eValue:正在设置哪个值?
  • eScope:您正在将此设置应用于什么类型的对象?
  • scopeArg:您想改变哪个对象? (若为全局范围则忽略)。 例如: 连接句柄、侦听套接字句柄、接口指针等。
  • eDataType:在 pValue 缓冲区中的是什么类型的数据? 它必须与变量的类型完全匹配!
  • pArg:要将其设为的值。

    您可传递 NULL 来移除此范围中的非全局设置,令该对象的值使用全局默认值。 而在全局范围中,传递 NULL 将重设任何自定义值并将其恢复为系统默认值。

    注意:当设置指针(如回调函数)时,请勿直接传递函数指针。 您的自变量应该为函数指针的指针。

char

const char *GetConfigValueInfo( ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigDataType *pOutDataType, ESteamNetworkingConfigScope *pOutScope );

获取关于配置值的信息。 返回值的名称,如果值不存在,则返回 NULL。 如果不需要其他输出参数,则其他输出参数均可以为 NULL。

IterateGenericEditableConfigValues

ESteamNetworkingConfigValue IterateGenericEditableConfigValues( ESteamNetworkingConfigValue eCurrent, bool bEnumerateDevVars );

循环访问当前环境中可以使用通用 UI 显示或编辑的所有配置值的列表。 要获取第一个可循环访问的值,请传入 k_ESteamNetworkingConfig_Invalid。 返回 k_ESteamNetworkingConfig_Invalid,表示列表到此结束。

bEnumerateDevVars 参数可用于纳入“dev”变量。 建议仅在“调试”或“开发”模式下编辑这些变量;一般来说,它们不应在零售环境中显示,因为怀有恶意的本地用户可能会利用它作弊。

常见情况的快捷操作

以下函数是常见使用情况中的方便快捷操作。
bool SetGlobalConfigValueInt32( ESteamNetworkingConfigValue eValue, int32 val ); bool SetGlobalConfigValueFloat( ESteamNetworkingConfigValue eValue, float val ); bool SetGlobalConfigValueString( ESteamNetworkingConfigValue eValue, const char *val ); bool SetConnectionConfigValueInt32( HSteamNetConnection hConn, ESteamNetworkingConfigValue eValue, int32 val ); bool SetConnectionConfigValueFloat( HSteamNetConnection hConn, ESteamNetworkingConfigValue eValue, float val ); bool SetConnectionConfigValueString( HSteamNetConnection hConn, ESteamNetworkingConfigValue eValue, const char *val );

杂项函数

AllocateMessage

SteamNetworkingMessage_t *AllocateMessage( int cbAllocateBuffer )
分配并初始化消息对象。 调用此函数的通常原因是将其传递至 ISteamNetworkingSockets::SendMessages。 返回的对象中所有相关字段都会清零。

您还可以申请此系统分配空间以容纳有效负载本身。 如果 cbAllocateBuffer 为非零的值,系统将分配内存以容纳至少 cbAllocateBuffer 字节的有效负载。 m_pData 将会指向被分配的缓冲区,m_cbSize 将会设为其大小,m_pfnFreeData 将会设为合适的函数以清空缓冲区。

如果 cbAllocateBuffer=0,则没有分配缓冲区。 m_pData 将为 NULL,m_cbSize 将为零,m_pfnFreeData 将为 NULL。 您将需要为每一个都进行设置。

GetLocalTimestamp

SteamNetworkingMicroseconds GetLocalTimestamp();

一个通用型高分辨率本地记时器,带有以下属性:
  • 保证单调性。
  • 初始值将至少为 24*3600*30*1e6,也就是总长为 30 天的微秒数。 这样一来,为 0 的时间戳值将总是为至少“30 天以前”。 此外,不会返回负数。
  • 从实际来看,无需担忧环绕/溢出。

SteamNetworkingMessage_t::m_usecTimeReceived 包含了来自同一记时器的时间戳。

如果您在调试程序下运行并停止该流程,时钟可能不会前进两个调用之间的完整自然时钟时间。 如果没有阻止该流程进行正常操作,时间戳的值将会跟随自然时钟时间,即便您没有频繁地调用该函数也是如此。

该值仅仅对该流程的本次运行有意义。 请勿将其与来自另一台计算机的值或同一流程的其他运行相比较。

SetDebugOutputFunction

oid SetDebugOutputFunction( ESteamNetworkingSocketsDebugOutputType eDetailLevel, FSteamNetworkingSocketsDebugOutput pfnFunc );

设置一个函数以接收便于调试的网络信息。

这可能在开发时极为有用,在与精通技术的终端用户进行故障排除时也可能很有帮助。 如果您有主控台日志或客户可以检查的其他日志,这些日志消息对于排除网络故障常常很有帮助。(尤其是任何警告/错误消息。)

细节级别表示在什么消息上调用回调。 数字越低表示越重要,而您传递的值是您希望最后一个(数字最高)收到回调的。 但如果在调试时,则应该使用
k_ESteamNetworkingSocketsDebugOutputType_Msg 或 k_ESteamNetworkingSocketsDebugOutputType_Warning。 为求最佳性能,请不要申请一个高细节级别然后又在回调时过滤掉消息。 相反地,请调用此函数以调整想要的细节级别。

此值控制大多数消息的细节级别。 您可以通过调整配置值 k_ESteamNetworkingConfig_LogLevel_Xxxxx 来控制各种子系统(可能仅适用于某些连接)的细节级别。

重要:此函数可以从一个服务线程,或者在我们拥有互斥体等情况下调用。您的回调函数必须是线程安全且快速的!请勿在该句柄内进行任何其他 Steamworks 调用。

Fake IP


“FakeIP”系统可用于与假设使用 IPv4 地址识别对等段的代码进行交互。 请参阅 ISteamNetworkingSockets,了解更多信息。

IsFakeIPv4

bool IsFakeIPv4( uint32 nIPv4 );

如果 IPv4 地址可能被用作“假”地址,返回 true。 此函数速度很快;它只是对 IP 做一些逻辑测试,不需要做任何查找操作。

GetRealIdentityForFakeIP

EResult GetRealIdentityForFakeIP( const SteamNetworkingIPAddr &fakeIP, SteamNetworkingIdentity *pOutRealIdentity );

获取与给定 FakeIP 关联的真实身份。

失败时,返回:
  • k_EResultInvalidParam:该 IP 不是 FakeIP。
  • k_EResultNoMatch:我们无法识别该 FakeIP,也不知道相应的身份。

有效连接中使用的 FakeIP 或分配给本地身份的 FakeIP 将始终有效。 最近被破坏的连接的 FakeIP 将在一段时间内继续返回结果,但不会一直返回结果。 在某个时间点,我们将忘记 FakeIP 以节省空间。 可以比较肯定地假设,您可以在连接被破坏后很快读回连接的真实身份。 但请勿无限期地等待。