网络函数,用于在客户端之间建立连接并发送数据,可能时遍历 NAT。
注意:此 API 已弃用,且可能会从未来发行的 Steamworks SDK 中移除。 请转而使用
ISteamNetworkingSockets 或
ISteamNetworkingMessages。 请参见
Steam 网络 概览,以获取更多信息。
成员函数
SteamNetworking
的成员函数通过全局访问器函数
SteamNetworking()
调用。
AcceptP2PSessionWithUser
bool AcceptP2PSessionWithUser( CSteamID steamIDRemote );
名称 | 类型 | 描述 |
steamIDRemote | CSteamID | 向我们发送了初始数据包的用户的 Steam ID。 |
这允许游戏指定是否接受传入的数据包。 需要在与远程主机建立真正的连接之前调用,让游戏有机会决定是否允许远程用户访问。
如果一个您最近并未向其发送数据包的远程用户尝试先向您发送一个数据包,您的游戏会收到
P2PSessionRequest_t 回调。 该回调包含希望向您发送数据包的用户的 Steam ID。 响应回调时,您应该查看是否想与此用户通话(如用户是否与您在同一大厅内),如果您愿意,接受连接;否则,如您不想与此用户通话,只需忽略请求即可。 如该用户继续向您发送数据包,另一个
P2PSessionRequest_t 将定期发布。 如您已对该用户调用了
SendP2PPacket,这会隐式接受会话请求。
注意,此函数只应在响应
P2PSessionRequest_t 回调时才能调用!
返回: bool
true, 表示成功;只有在
steamIDRemote
无效时为
false。
AllowP2PPacketRelay
bool AllowP2PPacketRelay( bool bAllow );
如果无法建立直接连接或 NAT 遍历,允许或禁止 P2P 连接回退到通过 Steam 服务器进行中继。
此函数只适用于设置此值后创建的连接,或在设置此值后需要自动重新连接的现有连接。
默认允许 P2P 数据包中继。
返回: bool
此函数始终返回
true。
CloseP2PChannelWithUser
bool CloseP2PChannelWithUser( CSteamID steamIDRemote, int nChannel );
名称 | 类型 | 描述 |
steamIDRemote | CSteamID | 要关闭与其连接的用户的 Steam ID。 |
nChannel | int | 要关闭的通道。 |
在特定通道结束与用户的通话后,关闭该 P2P 通道。
关闭通向某个用户的所有通道后,与该用户当前打开的会话也会关闭,而来自该用户的新数据会触发新的
P2PSessionRequest_t 回调。
返回: bool
true; 表示通道成功关闭。否则,如果与该用户没有正在进行中的会话或通道,返回
false。
CloseP2PSessionWithUser
bool CloseP2PSessionWithUser( CSteamID steamIDRemote );
名称 | 类型 | 描述 |
steamIDRemote | CSteamID | 要关闭与其连接的用户的 Steam ID。 |
应在结束与用户通信后调用此函数,可以释放后台所有分配给连接的资源。
如果远程用户再次尝试向您发送数据,将会发布新的
P2PSessionRequest_t 回调。
返回: bool
true; 表示会话成功关闭;否则,如果没有与
steamIDRemote
的连接,则返回
false。
CreateConnectionSocket
SNetSocket_t CreateConnectionSocket( uint32 nIP, uint16 nPort, int nTimeoutSec );
创建套接字,开始与远程目标进行连接。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: SNetSocket_tCreateListenSocket
SNetListenSocket_t CreateListenSocket( int nVirtualP2PPort, uint32 nIP, uint16 nPort, bool bAllowUseOfPacketRelay );
名称 | 类型 | 描述 |
nVirtualP2PPort | int | |
nIP | uint32 | |
nPort | uint16 | |
bAllowUseOfPacketRelay | bool | |
创建套接字,并侦听其他连接。
另一个客户端进行连接时,会触发
SocketStatusCallback_t 回调。
在您有多个端口的情况下,nVirtualP2PPort 为客户端将连接至的唯一 ID。
一般为 0,除非您希望有多重连接。
unIP 为要绑定至的本地 IP 地址。
如果您只想要默认的本地 IP,只需传入 0。
unPort 为需要使用的端口。
如果您不希望用户能够通过 IP/端口连接,而希望始终只是 P2P 连接,传入 0。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: SNetListenSocket_tCreateP2PConnectionSocket
SNetSocket_t CreateP2PConnectionSocket( CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay );
名称 | 类型 | 描述 |
steamIDTarget | CSteamID | |
nVirtualPort | int | |
nTimeoutSec | int | |
bAllowUseOfPacketRelay | bool | |
创建套接字,开始与远程目标进行连接。
能通过已知 Steam ID(客户端或游戏服务器)连接,或直接连接至 IP。
成功后会触发 SocketStatusCallback_t 回调。
失败或超时会触发 SocketStatusCallback_t 回调,在 m_eSNetSocketState 内包含失败代码。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: SNetSocket_tDestroyListenSocket
bool DestroyListenSocket( SNetListenSocket_t hSocket, bool bNotifyRemoteEnd );
销毁侦听套接字将自动终止从该套接字生成的所有常规套接字。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
DestroySocket
bool DestroySocket( SNetSocket_t hSocket, bool bNotifyRemoteEnd );
如果有与套接字的连接,断开此连接,并使句柄失效。
将丢弃此套接字上的任何未读数据。
如 bNotifyRemoteEnd 已设置,在远端确认断开连接前,不会完全销毁套接字。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
GetListenSocketInfo
bool GetListenSocketInfo( SNetListenSocket_t hListenSocket, uint32 *pnIP, uint16 *pnPort );
返回侦听套接字绑定至的本地端口。
如果套接字设置为只侦听 P2P 连接,则 *pnIP 与 *pnPort 将为 0。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
GetMaxPacketSize
int GetMaxPacketSize( SNetSocket_t hSocket );
获取数据包最大字节量。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: int
GetP2PSessionState
bool GetP2PSessionState( CSteamID steamIDRemote, P2PSessionState_t *pConnectionState );
在
P2PSessionState_t 结构中填入有关此连接的详细信息,如是否有使用中的连接;连接中排入队列里的字节数量;最后一个错误代码(如有);是否在使用中继服务器;远程用户的 IP 和端口(如已知)。
此函数应只用于调试。
返回: bool
true, 表示
pConnectionState
已填写;如果与指定用户无打开的会话,则返回
false。
示例:P2PSessionState_t p2pSessionState;
SteamNetworking()->GetP2PSessionState( steamIDremote, &p2pSessionState );
GetSocketConnectionType
ESNetSocketConnectionType GetSocketConnectionType( SNetSocket_t hSocket );
返回 true 以描述套接字最终如何连接。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: ESNetSocketConnectionTypeGetSocketInfo
bool GetSocketInfo( SNetSocket_t hSocket, CSteamID *pSteamIDRemote, int *peSocketStatus, uint32 *punIPRemote, uint16 *punPortRemote );
返回指定套接字的信息,填入指针的内容。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
IsDataAvailable
bool IsDataAvailable( SNetListenSocket_t hListenSocket, uint32 *pcubMsgSize, SNetSocket_t *phSocket );
检查与此侦听套接字连接的任何套接字中是否有数据。
如果没有剩余数据,返回 false。
在 *pcubMsgSize 填入下一条消息的字节大小。
将有可用数据的套接字填入 *phSocket 中。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
IsDataAvailableOnSocket
bool IsDataAvailableOnSocket( SNetSocket_t hSocket, uint32 *pcubMsgSize );
如果没有剩余数据,返回 false。
在 *pcubMsgSize 填入下一条消息的字节大小。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
IsP2PPacketAvailable
bool IsP2PPacketAvailable( uint32 *pcubMsgSize, int nChannel = 0 );
名称 | 类型 | 描述 |
pcubMsgSize | uint32 * | 返回数据包的大小。 |
nChannel | int | 要检查其中是否有数据包可用的通道。 |
检查是否有 P2P 数据包可读,如有,获取消息大小。
应在您使用的每个通道中循环调用。 如有数据包可用,您应调用
ReadP2PPacket 获取数据包数据。
返回: bool
true, 表示数据包可用;否则,返回
false。
ReadP2PPacket
bool ReadP2PPacket( void *pubDest, uint32 cubDest, uint32 *pcubMsgSize, CSteamID *psteamIDRemote, int nChannel = 0 );
名称 | 类型 | 描述 |
pubDest | void * | 以复制至此缓冲区的方式返回数据包数据。 |
cubDest | uint32 | 分配给 pubDest 的大小。 应与 IsP2PPacketAvailable 返回的大小或您最大数据包的大小相同。 |
pcubMsgSize | uint32 * | 返回数据包的大小。 |
psteamIDRemote | CSteamID * | 返回发送此数据包的用户的 Steam ID。 |
nChannel | int | 发送数据包的通道。 |
在另一位用户通过
SendP2PPacket 发送的数据包中读取。
如果
cubDest
缓冲区过小,无法容纳该数据包,则消息会截断。
调用不阻止,如无数据可用,会返回 false。
在调用此函数前,您应调用
IsP2PPacketAvailable。
返回: bool
true, 表示成功读取数据包;如无数据包可用,则返回
false。
示例:uint32 msgSize = 0;
while ( SteamNetworking()->IsP2PPacketAvailable( &msgSize ) )
{
void *packet = malloc( msgSize );
CSteamID steamIDRemote;
uint32 bytesRead = 0;
if ( SteamNetworking()->ReadP2PPacket( packet, msgSize, &bytesRead, &steamIDRemote ) )
{
// 消息调度代码填入此处
}
free( packet );
}
RetrieveData
bool RetrieveData( SNetListenSocket_t hListenSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize, SNetSocket_t *phSocket );
从与此侦听套接字连接的任何套接字中检索数据。
在 pubDest 填入消息内容。
消息应一直保持完整,与发送时大小相同(即打包,而非流式传输)。
如果 *pcubMsgSize < cubDest,则只写入部分数据。
如果无数据可用,返回 false。
将有可用数据的套接字填入 *phSocket 中。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
RetrieveDataFromSocket
bool RetrieveDataFromSocket( SNetSocket_t hSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize );
在 pubDest 中填入消息内容。
消息应一直保持完整,与发送时大小相同(即打包,而非流式传输)。
如果 *pcubMsgSize < cubDest,则只写入部分数据。
如果无数据可用,返回 false。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
返回: bool
SendDataOnSocket
bool SendDataOnSocket( SNetSocket_t hSocket, void *pubData, uint32 cubData, bool bReliable );
发送数据。
须为已连接套接字的句柄。
数据均通过 UDP 发送,因此发送大小不超过 1200 字节。超过后许多路由器就会开始丢包。
请小心使用可靠标志。虽然重新发送率较高, 接收数据时,
还是可能会导致延迟(像 TCP 一样)。
返回: bool
SendP2PPacket
bool SendP2PPacket( CSteamID steamIDRemote, const void *pubData, uint32 cubData, EP2PSend eP2PSendType, int nChannel = 0 );
名称 | 类型 | 描述 |
steamIDRemote | CSteamID | 要向其发送数据包的目标用户。 |
pubData | const void * | 供数据包数据发送的原始字节数组。 此数据包最大大小由 eP2PSendType 定义。 |
cubData | uint32 | pubData 的字节大小。 |
eP2PSendType | EP2PSend | 指定您希望数据传输的方式,如可靠、不可靠、缓冲,等等。 |
nChannel | int | 作为虚拟端口发送本数据包,且允许您将消息传送至不同系统的通道。 您必须在另一端用同一通道号码调用 ReadP2PPacket,以获取另一端的数据。 使用不同通道与同一用户通话仍旧会使用同一基础 P2P 连接,以节省资源。 如果使用主要通道,或您不使用本功能,写入 0。 |
给指定用户发送 P2P 数据包。
此 API 不产生会话,而是自动遍历 NAT 或建立 Steam 中继服务器连接。
注意: 在运行 NAT 遍历代码时,第一个数据包发送可能会延迟。
参见
EP2PSend ,了解发送数据包的不同方法。
您所发送的数据为任意类型,您可使用现成可用的系统,如
Protocol Buffers 或
Cap'n Proto,对数据包进行高效编码,或者您也可以创建自己的消息传送系统。
返回: bool
触发
P2PSessionRequest_t 回调。
true, 表示数据包发送成功。
请注意这并不意味着数据包已成功接收。如果超时 20 秒后用户仍无法收到数据包,会通过
P2PSessionConnectFail_t 回调发布错误。
false, 则表示出现以下情况之一:
- 数据包对于发送类型而言过大。
- 目标 Steam ID 无效。
- 排入队列等待发送的字节过多。
回调
以下是可以通过调用
SteamAPI_RunCallbacks 触发的回调。 其中许多回调会因为响应
ISteamNetworking
的成员函数而直接触发。
P2PSessionConnectFail_t
指定用户无法收到数据包时调用。
所有已排入队列但此时仍未发送的数据包会丢弃,再次尝试发送会重新尝试进行连接(但如果再次失败,会再次丢包)。
P2PSessionRequest_t
用户希望通过
SendP2PPacket 与我们在 P2P 通道通信。 响应时,如果您希望打开与用户之间的网络通道,需要调用
AcceptP2PSessionWithUser。
名称 | 类型 | 描述 |
m_steamIDRemote | CSteamID | 希望与我们开始 P2P 会话的用户。 |
关联函数: SendP2PPacketSocketStatusCallback_t
套接字状态发生改变时调用,作为
CreateListenSocket 及
CreateP2PConnectionSocket 调用的一部分。
这是基于伯克利套接字(Berkeley TCP socket)模型设计的一套旧版函数集中的一部分。 您应优先使用 P2P 函数,因为此类函数更可靠,而旧的函数最终会被移除。
名称 | 类型 | 描述 |
m_hSocket | SNetSocket_t | 用以与远程主机收发数据的套接字。 |
m_hListenSocket | SNetListenSocket_t | 这是我们当时正在侦听的服务器套接字;如果为拨出的连接则为 NULL。 |
m_steamIDRemote | CSteamID | 这是我们已连接至的远程 Steam ID(若有) |
m_eSNetSocketState | int | 套接字状态, ESNetSocketState |
结构
以下为 ISteamNetworking 中的函数可能会返回和/或与之互动的结构。
P2PSessionState_t
与指定用户的连接状态,由
GetP2PSessionState 返回。 此为后台信息,说明前一次调用
SendP2PPacket 发生的情况。 此函数通常不用于调试之外的目的。
名称 | 类型 | 描述 |
m_bConnectionActive | uint8 | 我们与用户是否有使用中的打开的连接?是(true)或否(false)。 |
m_bConnecting | uint8 | 我们是否正尝试与用户建立连接?是(true)或否(false)。 |
m_eP2PSessionError | uint8 | 套接字上记录的最后错误。 会返回 EP2PSessionError。 |
m_bUsingRelay | uint8 | 是通过 Steam 中继服务器进行连接吗?是(true)或否(false) |
m_nBytesQueuedForSend | int32 | 排入队列待向用户发送的字节数量。 |
m_nPacketsQueuedForSend | int32 | 排入队列待向用户发送的数据包数量。 |
m_nRemoteIP | uint32 | 若设置,为远程主机的 IP。 可以是 Steam 中继服务器。 仅用于与旧版验证 API 兼容。 |
m_nRemotePort | uint16 | 若设置,为远程主机的端口。 可以是 Steam 中继服务器。 仅用于与旧版验证 API 兼容。 |
枚举
以下是经过定义来与 ISteamNetworking 一起使用的枚举。
EP2PSend
指定
SendP2PPacket 的发送类型。
通常
k_EP2PSendUnreliable
用于类似 UDP 的数据包,而
k_EP2PSendReliable
用于类似 TCP 的数据包。
名称 | 值 | 描述 |
k_EP2PSendUnreliable | 0 | 基础 UDP 发送。 数据包不能大于 1200 字节(MTU 的通常大小)。 可能会丢失,或顺序错乱(罕见)。 发送 API 确实对基础连接有一定了解,因此如果没有完成 NAT 遍历或在连接时发生已识别的调整,数据包将会被批处理,直至连接再次打开。 |
k_EP2PSendUnreliableNoDelay | 1 | 同上,但如果基础 P2P 连接仍未建立,数据包会被丢弃。 这如果用于发送给远程主机的第一个数据包上,几乎可以肯定数据包会丢失。 这只对不应缓冲的数据类型有用,即语音有效负载数据包。 |
k_EP2PSendReliable | 2 | 可靠的消息发送。 每条消息可发送高达 1MB 的数据。 可在后台对消息进行碎片化或重组,以及用滑动窗口高效发送大型数据区块。 |
k_EP2PSendReliableWithBuffering | 3 | 同上,但使用 Nagle 算法发送,发送内容将累积,直至达到当前 MTU 大小(通常约 1200 字节,但可能会变化),或已过去大约 200 毫秒(Nagle 算法)。 如果您想发送一系列较小的消息,但已将他们合并成一个数据包,这将非常有用。 因为所有可靠的数据流都已排序,您可用 k_EP2PSendReliableWithBuffering 发送几个小消息,然后用普通的 k_EP2PSendReliable 强制发送所有已缓冲的数据。 |
EP2PSessionError
SendP2PPacket 返回的可能的错误列表,将在
P2PSessionConnectFail_t 回调中发送。
名称 | 值 | 描述 |
k_EP2PSessionErrorNone | 0 | 无错误。 |
k_EP2PSessionErrorNotRunningApp | 1 | 目标用户并未运行相同游戏。 |
k_EP2PSessionErrorNoRightsToApp | 2 | 本地用户不拥有正在运行的应用。 |
k_EP2PSessionErrorDestinationNotLoggedIn | 3 | 目标用户未与 Steam 连接。 |
k_EP2PSessionErrorTimeout | 4 | 连接超时,原因是目标用户未响应,也许他们不在调用 AcceptP2PSessionWithUser。 企业防火墙也可将其屏蔽(NAT 遍历并非防火墙遍历),请确保 UDP 端口 3478、4379 及 4380 在出站方向开放。 |
k_EP2PSessionErrorMax | 5 | 未使用。 |
ESNetSocketConnectionType
描述套接字当前如何连接。 仅由旧版网络 API 使用。
名称 | 值 | 描述 |
k_ESNetSocketConnectionTypeNotConnected | 0 | |
k_ESNetSocketConnectionTypeUDP | 1 | |
k_ESNetSocketConnectionTypeUDPRelay | 2 | |
ESNetSocketState
连接进程指示器,由
CreateP2PConnectionSocket 使用。
名称 | 值 | 描述 |
k_ESNetSocketStateInvalid | 0 | |
k_ESNetSocketStateConnected | 1 | 通信有效。 |
k_ESNetSocketStateInitiated | 10 | 建立连接时的状态。 连接状态机器已开始。 |
k_ESNetSocketStateLocalCandidatesFound | 11 | p2p 连接。 已找到本地 IP 信息。 |
k_ESNetSocketStateReceivedRemoteCandidates | 12 | 已通过 Steam 后端接收到远程机器的 IP 信息。 |
k_ESNetSocketStateChallengeHandshake | 15 | 直接连接。 已从服务器接收到质询数据包。 |
k_ESNetSocketStateDisconnecting | 21 | 失败状态。 API 已将其关闭,正在告知另一端。 |
k_ESNetSocketStateLocalDisconnect | 22 | API 已将其关闭,我们已完成关闭。 |
k_ESNetSocketStateTimeoutDuringConnect | 23 | 在尝试创建连接时超时。 |
k_ESNetSocketStateRemoteEndDisconnected | 24 | 远端已断开与我们的连接。 |
k_ESNetSocketStateConnectionBroken | 25 | 连接已中断。另一端已消失或本地网络连接中继。 |
Typedefs
以下是经过定义来与 ISteamNetworking 一起使用的 typedef。
名称 | 基类型 | 描述 |
SNetListenSocket_t | uint32 | CreateListenSocket() |
SNetSocket_t | uint32 | 套接字句柄 CreateP2PConnectionSocket() |
常量
以下是经过定义与 ISteamNetworking 一起使用的常量。
名称 | 类型 | 值 | 描述 |
STEAMNETWORKING_INTERFACE_VERSION | const char * | "SteamNetworking005" | |