接入了Epic在线系统(EOS)SDK的游戏能够借助P2P接口来设置和管理用户之间的点对点(P2P)连接。用户能够直接通过此接口相互收发数据,通常用于多人游戏。使用EOS P2P接口建立的连接只在经过身份验证的用户之间建立,并且默认使用DTLS确保安全,这存在两项明显优势。首先,处理P2P连接的速度大幅提高,因为EOS身份验证大幅减少了重新协商连接的需求。其次,对于SDK用户而言,安全处理连接过程本身已大幅简化,无需再进行详细的网络套接字管理,将大多数函数简缩为需要将什么数据发送至什么用户。
访问P2P接口
要使用EOS P2P接口中的函数,必须先从 平台接口 函数 EOS_Platform_GetP2PInterface
中获取有效的 EOS_HP2P
柄,因为所有P2P接口函数都会用到该柄。有关平台接口和此函数的更多信息,请参见EOS平台接口上的页面。
管理P2P连接
P2P接口将结构 EOS_P2P_SocketId
用作点之间连接的游戏专属辨识符。与连接有关的大多数P2P函数要么要求 EOS_P2P_SocketId
与连接请求关联,要么返回 EOS_P2P_SocketId
来指定接收的连接请求与哪个连接关联。 EOS_P2P_SocketId
由以下参数组成:
参数 | 说明 |
---|---|
ApiVersion | 版本字段。此字段必须设为 EOS_P2P_SOCKETID_API_LATEST 。 |
SocketName | 用于验证多人游戏中来自未知点的所有传入连接的值。SocketName必须包含1?2个以非空字符结尾的字母数字组合。 |
SocketName
字段可以是面向所有连接的单一值,也可以是多人游戏会话中仅特定玩家知悉的秘密值。由于接受P2P连接会将用户的IP地址暴露给正在连接的点,因此千万不要盲目接受连接请求。
通常,用户还需要一个有效的 EOS_ProductUserId
,以便在发送数据时标识自己,并指定想要发送数据的目标用户。
除非显式标记为可选,否则P2P接口中的所有函数参数及其关联值均为必填项。其中包括输出参数,P2P接口经常使用它们来输出用于异步函数或事件响应的数据。如果函数的返回类型为 EOS_EResult
,并且返回值不是 EOS_Success
,则请注意,除非另有说明,否则该函数提供的输出参数均为未设置状态。
请求连接
当本地用户尝试通过 EOS_P2P_SendPacket
等函数向远程用户发送信息时,P2P接口将自动请求开放这两个用户之间的连接, EOS_P2P_SocketId
充当连接辨识符。发送信息的用户会自动接受自己的SocketId请求,而接收信息的用户通常必须通过侦听传入连接请求并使用 EOS_P2P_AcceptConnection
函数来接受请求。
如果P2P连接尚未开放,则所有需要开放P2P连接的操作都可以用于请求和接受P2P连接。举例而言, EOS_P2P_AcceptConnection
可用于请求与远程用户的P2P连接;如果本地用户正在尝试使用套接字ID发送信息,造成已发出连接请求的状况,则可以使用 EOS_P2P_SendPacket
接受远程用户的P2P连接请求。实际上,这意味着可以使用 EOS_P2P_AcceptConnection
抢先接受给定SocketId发出的下一个连接请求。
如果和某个特定用户之间开放了多个连接,则仅须协商第一个连接。这样可以大幅提升通过后续连接请求接收数据的速度。
接收连接请求通知
当用户收到连接请求时,将向所有绑定的 点连接请求处理程序 发送通知事件。
要使用新的点连接请求处理程序侦听连接请求,请使用 EOS_P2P_AddNotifyPeerConnectionRequest
来绑定要用于响应传入连接请求的函数。 EOS_P2P_AddNotifyPeerConnectionRequest
函数拥有以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_AddNotifyPeerConnectionRequestOptions 结构体的指针。 |
ClientData (可选) | 事件触发时将返回给调用者的数据的指针。 |
ConnectionRequestHandler | 一个函数,充当点连接请求处理程序以响应传入连接请求。该函数必须将 EOS_P2P_OnIncomingConnectionRequestInfo 结构的指针用作参数。 |
EOS_P2P_AddNotifyPeerConnectionRequestOptions
结构由以下参数组成:
参数 | 说明 |
---|---|
ApiVersion | 版本字段。设为 EOS_P2P_ADDNOTIFYPEERCONNECTIONREQUEST_API_LATEST |
LocalUserId | 设为正在侦听传入连接请求的本地用户ID。 |
SocketId (可选) | 用来过滤连接请求的有效 EOS_P2P_SocketId 结构的指针。 |
EOS_P2P_AddNotifyPeerConnectionRequest
函数将在成功时返回有效的 EOS_NotificationId
,在失败时返回值 EOS_INVALID_NOTIFICATIONID
。
可以使用 EOS_P2P_RemoveNotifyPeerConnectionRequest
函数删除点连接请求处理程序,该函数需要以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
NotificationId | 从 EOS_P2P_AddNotifyPeerConnectionRequest 返回的有效 EOS_NotificationId ,用于标识要删除的点连接请求处理程序。 |
接受连接
EOS_P2P_AcceptConnection
函数可以用来接受已请求的连接,或开始新的连接请求。在建立连接并用于发送数据之前,两方用户都必须接受给定SocketId的连接。如果 bDisableAutoAcceptConnection
设置为 EOS_TRUE
,则尝试开启连接的用户都必须调用 EOS_P2P_AcceptConnection
。
要调用 EOS_P2P_AcceptConnection
函数,必须提供以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_AcceptConnectionOptions 结构的指针。 |
EOS_P2P_AcceptConnectionOptions
结构包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_ACCEPTCONNECTION_API_LATEST |
LocalUserId | 设为接受连接的本地用户的 EOS_ProductUserId 。 |
RemoteUserId | 设为本地用户要连接的远程用户的 EOS_ProductUserId 。 |
SocketId | 要接受其连接的有效 EOS_P2P_SocketId 结构体的指针。 |
如果提供的任何输入无效,则 EOS_P2P_AcceptConnection
函数将返回 EOS_InvalidParameters
值。如果提供的信息有效,系统将返回 EOS_Success
,表示该连接已被本地接受,并且能够在远程用户也接受该连接时发送数据。在连接关闭事件触发前多次调用 EOS_P2P_AcceptConnection
无效。
关闭连接
EOS_P2P_CloseConnection
函数可以用来拒绝已请求的连接,或关闭此前被特定用户接受的连接。如果与特定用户建立的所有连接都已关闭,则后备套接字连接也将很快销毁。 EOS_P2P_CloseConnection
函数需要以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_CloseConnectionOptions 结构体的指针。 |
EOS_P2P_CloseConnectionOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_CLOSECONNECTION_API_LATEST 。 |
LocalUserId | 设为关闭或拒绝连接的本地用户的 EOS_ProductUserId 。 |
RemoteUserId | 设为连接正在关闭或拒绝的远程用户的 EOS_ProductUserId 。 |
SocketId | 要关闭或拒绝连接的有效 EOS_P2P_SocketId 结构的指针。 |
EOS_P2P_CloseConnection
函数将返回 EOS_InvalidParameters
值,表示所提供的函数输入无效,或者将返回 EOS_Success
值。在这种情况下,所提供的输入有效且连接将关闭或连接请求将被无提醒拒绝。
EOS_P2P_CloseConnections
函数可用于关闭或拒绝特定SocketId上的所有连接,而非来自特定用户的连接。在会话结束时可以使用该函数,丢弃该会话的所有相关连接。 EOS_P2P_CloseConnections
函数需要以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_CloseConnectionsOptions 结构体的指针。 |
EOS_P2P_CloseConnectionsOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_CLOSECONNECTIONS_API_LATEST |
LocalUserId | 设为 EOS_ProductUserId ,此ID属于正在关闭与请求所有SocketId连接的本地用户。 |
SocketId | 指针,指向要关闭所有连接的有效 EOS_P2P_SocketId 结构体。 |
如果提供的任何输入无效,该函数将返回结果 EOS_InvalidParameters
;或者如果提供的信息有效且与指定 SocketId
的所有连接已成功关闭,则该函数将返回 EOS_Success
。
接收连接关闭通知
当已开放或待处理的连接关闭时,将触发 连接关闭事件 ,通知应用程序并允许其响应。要为连接关闭事件创建处理程序,请使用 EOS_P2P_AddNotifyPeerConnectionClosed
函数,该函数需要以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_AddNotifyPeerConnectionClosedOptions 结构体的指针。 |
ClientData (可选) | 事件触发时将返回给调用者的数据的指针。 |
ConnectionClosedHandler | 连接关闭事件触发时将调用的函数。该函数必须将 EOS_P2P_OnRemoteConnectionClosedInfo 结构体的指针作为参数传递。 |
EOS_P2P_AddNotifyPeerConnectionClosedOptions
结体构包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_ADDNOTIFYPEERCONNECTIONCLOSED_API_LATEST 。 |
LocalUserId | 设为正在侦听要关闭连接的本地用户的 EOS_ProductUserId 。 |
SocketId (可选) | 要过滤连接关闭事件的有效 EOS_P2P_SocketId 结构体的指针。 |
EOS_P2P_AddNotifyPeerConnectionClosed
函数返回 EOS_NotificationId
,可用于识别连接关闭事件处理程序。
可以调用函数 EOS_P2P_RemoveNotifyPeerConnectionClosed
移除连接关闭事件处理程序,该函数拥有以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
NotificationId | 从 EOS_P2P_AddNotifyPeerConnectionClosed 返回的有效 EOS_NotificationId 。 |
通过P2P连接收发数据
成功建立P2P连接后,用户可以通过连接收发数据。
发送数据
EOS_P2P_SendPacket
函数会安全地将数据包发送给另一个用户。如果已经存在该点的开放连接,则其将立即发送。如果没有开放连接,则将请求新的连接。 EOS_P2P_SendPacket
函数拥有以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_SendPacketOptions 结构体的指针。 |
EOS_P2P_SendPacketOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_SENDPACKET_API_LATEST 。 |
LocalUserId | 设为正在发送数据包的本地用户的 EOS_ProductUserId 。 |
RemoteUserId | 设为数据包发送目标远程用户的 EOS_ProductUserId 。 |
SocketId | 有效 EOS_P2P_SocketId 的指针。 |
Channel | 设为发送该数据的信道。 |
DataLengthBytes | 设为要从 Data 发送的字节数。 |
Data | 要从中发送 DataLengthBytes 的数据缓冲开始的指针。 |
bAllowDelayedDelivery | 如果我们没有已建立的连接并且此参数为false,则该数据包将被无提示丢弃。否则直到连接开放、或使用 EOS_P2P_CloseConnection 或 EOS_P2P_CloseConnection 关闭连接之前,数据包都将处于队列中。 |
Reliability | 设置此数据包的传递可靠性。可靠性可以是 EOS_PR_UnreliableUnordered 、 EOS_PR_ReliableUnordered 或 EOS_PR_ReliableOrdered 。 |
bDisableAutoAcceptConnection | 如果其值为 true ,则 EOS_P2P_SendPacket 不会自动与 RemoteUserId 建立连接,因此只要关闭了连接,你就必须先显式地调用 EOS_P2P_AcceptConnection 。如果其值为 false ,只要连接尚未建立, EOS_P2P_SendPacket 就会在被调用时自动接受并启动连接。 |
如果提供的任何输入无效,则此函数将返回 EOS_InvalidParameters
;如果提供的信息有效且可以发送,则此函数将返回 EOS_Success
。注意,返回成功仅表示可以成功发送数据包,而不表示数据包是否成功送达。由于数据发送不可靠,因此不能保证成功送达。
接收数据
P2P接口将用户内部接收的数据包排队,等待对 EOS_P2P_ReceivePacket
函数的调用,以便将其从队列中移除、并将其数据存储在缓冲中。此函数采用以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | 有效 EOS_P2P_ReceivePacketOptions 结构体的指针。 |
OutPeerId | 一个指针,指向写出数据包发送者的 EOS_ProductUserId 值。 |
OutSocketId | 一个指针,指向写入关联SocketId数据的 EOS_P2P_SocketId 结构。 |
OutChannel | 一个指针,指向写入数据包关联信道 uint8_t 。 |
OutData | 一个指针,指向已接收数据包数据要写入的缓冲。此缓冲必须为此函数 Options 中 MaxDataSizeBytes 的大小。 |
OutBytesWritten | 一个指针,指向将记录写入 OutData 的字节数的 uint32_t 。 |
EOS_P2P_ReceivePacketOptions
结构包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 版本字段。设为 EOS_P2P_RECEIVEPACKET_API_LATEST |
LocalUserId | 设为请求已接收数据包的本地用户的 EOS_ProductUserId 。 |
MaxDataSizeBytes | 可以安全写入 OutData 缓冲的最大字节数。 |
RequestedChannel (可选) | 设置后,则仅接收属于该信道的数据包。 |
如果任何输入参数无效,函数将返回 EOS_InvalidParameters
。如果成功将数据包及其相关数据复制到所有输出参数中,将返回 EOS_Success
;如果没有数据包可满足请求,将返回 EOS_NotFound
。值得注意的是,只有在函数返回值 EOS_Success
时,才会写入输出参数。
EOS_P2P_ReceivePacketOptions
除了使用 OutData
指定缓冲本身之外,还要求您指定可以通过 MaxDataSizeBytes
安全写入缓冲的数据量。如果提供的缓冲太小而无法容纳下一个数据包,则数据将被无提示截断为所提供缓冲的长度。在 OutData
中提供一个 NULL
缓冲,且在 MaxDataSizeBytes
中将大小设为0,可以完全丢弃数据包的数据。也可以安全地使用 EOS_P2P_MAX_PACKET_SIZE
的缓冲存储来自数据包的数据,但是建议在调用 EOS_P2P_ReceivePacket
之前调用 EOS_P2P_GetNextReceivedPacketSize
,获取数据包数据的确切大小。由于DTLS/SCTP/UDP的数据包限制, EOS_P2P_MAX_PACKET_SIZE
是1170。
建议经常调用 EOS_P2P_RecievePacket
,防止内部数据包队列被填满。如果内部数据包队列已满,则传入数据包将丢失,不会被接收。
确定数据包大小
EOS_P2P_GetNextReceivedPacketSize
将获取内部队列中下一个数据包的大小(以字节为单位),不会将其从队列中删除,函数采用以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_GetNextReceivedPacketSizeOptions 结构的指针。 |
OutPacketSizeBytes | 可为调用此函数的用户存储下一个数据包大小的 uint32_t 的指针。 |
EOS_P2P_GetNextReceivedPacketSizeOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_GETNEXTRECEIVEDPACKETSIZE_API_LATEST |
LocalUserId | 设为请求下一个数据包大小的本地用户的 EOS_ProductUserId 。 |
RequestedChannel (可选) | 设置后,则仅返回属于该信道的下一个数据包的大小。 |
如果任何输入参数无效,则此函数将返回 EOS_InvalidParameters
的值;如果成功将数据包数据大小复制到 OutPacketSizeBytes
,则该函数将返回 EOS_Success
的值。如果没有可用数据,该函数将返回 EOS_NotFound
的值。
确定NAT类型
虽然P2P接口将尝试NAT遍历,但当一个或多个点拥有限制性NAT时,有时可能无法接收传入连接。在这种情况下需要中继,以便在NAT遍历失败时自动使用。为了帮助确定用户是否可以轻松连接到点,P2P接口可以查询与互联网有关的本地用户的 NAT类型 。NAT类型由 EOS_ENATType
表示,可以采用以下值:
值 | 说明 |
---|---|
EOS_NAT_Unknown | NAT类型目前未知,或者我们无法准确确定。 |
EOS_NAT_Open | 所有类型的点都能直接与您建立连接。 |
EOS_NAT_Moderate | 在不使用中继服务器的情况下可以直接连接到其他适中和开放点。 |
EOS_NAT_Strict | 在不使用中继服务器的情况下只能直接连接到开放点。 |
EOS_P2P_QueryNATType
函数可以异步确定当前连接的NAT类型。该函数通过将多个数据包发送到远程服务器来实现此目的,这些服务器以本地应用程序使用的IP和端口进行响应。请注意,请求正在进行时,对 EOS_P2P_QueryNATType
的其他调用将被分组到该第一个请求中,并且不会启动新请求。 EOS_P2P_QueryNATType
采用以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_QueryNATTypeOptions 结构体的指针。 |
ClientData (可选) | 查询完成时将返回给调用者的数据的指针。 |
NATTypeQueriedHandler | 查询完成时要调用函数的指针。 |
EOS_P2P_QueryNATTypeOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 版本字段。设为 EOS_P2P_QUERYNATTYPE_API_LATEST 。 |
因为NAT类型查询为异步进行,所以此函数不会直接返回值。而是通过 NAT类型查询处理程序 输出用户的NAT类型,该函数注册为查询完成时出现。在某些情况下,该查询将无法确定用户的NAT类型,而是返回 EOS_NAT_Unknown
的值。
当 EOS_P2P_QueryNATType
完成时,将缓存用户NAT类型的值,您可以改为调用函数 EOS_P2P_GetNATType
立即返回该值。仅在 EOS_P2P_QueryNATType
至少完成一次时,此值才能成功返回。要调用 EOS_P2P_GetNATType
函数,必须提供以下参数:
参数 | 说明 |
---|---|
Handle | 从平台接口接收的有效 EOS_HP2P 柄。 |
Options | EOS_P2P_GetNATTypeOptions 结构体的指针。 |
OutNATType | 一个指针,指向一个 EOS_ENATType 对象,此对象设为此前由 EOS_P2P_QueryNATType 查询的缓存值。 |
EOS_P2P_GetNATTypeOptions
结构体包含以下参数:
参数 | 说明 |
---|---|
ApiVersion | 设为 EOS_P2P_GETNATTYPE_API_LATEST 。 |
如果过去成功调用过 EOS_P2P_QueryNATType
,则 EOS_P2P_GetNATType
函数将返回 EOS_Success
。如果此前没有调用过 EOS_P2P_QueryNATType
,或者尚未完成调用,则返回 EOS_NotFound
。