NAT P2P接口

用户之间收发数据的接口及相关的网络功能。

阅读时间15分钟

接入了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 柄。
OptionsEOS_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 柄。
NotificationIdEOS_P2P_AddNotifyPeerConnectionRequest 返回的有效 EOS_NotificationId ,用于标识要删除的点连接请求处理程序。

接受连接

EOS_P2P_AcceptConnection 函数可以用来接受已请求的连接,或开始新的连接请求。在建立连接并用于发送数据之前,两方用户都必须接受给定SocketId的连接。如果 bDisableAutoAcceptConnection 设置为 EOS_TRUE ,则尝试开启连接的用户都必须调用 EOS_P2P_AcceptConnection

要调用 EOS_P2P_AcceptConnection 函数,必须提供以下参数:

参数说明
Handle从平台接口接收的有效 EOS_HP2P 柄。
OptionsEOS_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 柄。
OptionsEOS_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 柄。
OptionsEOS_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 柄。
OptionsEOS_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 柄。
NotificationIdEOS_P2P_AddNotifyPeerConnectionClosed 返回的有效 EOS_NotificationId

通过P2P连接收发数据

成功建立P2P连接后,用户可以通过连接收发数据。

发送数据

EOS_P2P_SendPacket 函数会安全地将数据包发送给另一个用户。如果已经存在该点的开放连接,则其将立即发送。如果没有开放连接,则将请求新的连接。 EOS_P2P_SendPacket 函数拥有以下参数:

参数说明
Handle从平台接口接收的有效 EOS_HP2P 柄。
OptionsEOS_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_CloseConnectionEOS_P2P_CloseConnection 关闭连接之前,数据包都将处于队列中。
Reliability设置此数据包的传递可靠性。可靠性可以是 EOS_PR_UnreliableUnorderedEOS_PR_ReliableUnorderedEOS_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一个指针,指向已接收数据包数据要写入的缓冲。此缓冲必须为此函数 OptionsMaxDataSizeBytes 的大小。
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 柄。
OptionsEOS_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_UnknownNAT类型目前未知,或者我们无法准确确定。
EOS_NAT_Open所有类型的点都能直接与您建立连接。
EOS_NAT_Moderate在不使用中继服务器的情况下可以直接连接到其他适中和开放点。
EOS_NAT_Strict在不使用中继服务器的情况下只能直接连接到开放点。

EOS_P2P_QueryNATType 函数可以异步确定当前连接的NAT类型。该函数通过将多个数据包发送到远程服务器来实现此目的,这些服务器以本地应用程序使用的IP和端口进行响应。请注意,请求正在进行时,对 EOS_P2P_QueryNATType 的其他调用将被分组到该第一个请求中,并且不会启动新请求。 EOS_P2P_QueryNATType 采用以下参数:

参数说明
Handle从平台接口接收的有效 EOS_HP2P 柄。
OptionsEOS_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 柄。
OptionsEOS_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