该存储库提供了由 Valve Software 创建和维护的 GameNetworkingSockets 库的托管 C# 抽象。在开始之前,您需要构建具有所有必需依赖项的本机库。
该项目正在根据本机库的版本进行更新。
可以使用支持 C# 3.0 或更高版本的任何可用编译平台来构建托管程序集。
定义VALVESOCKETS_SPAN
以启用对 Span 的支持。请按照以下步骤操作,以实现对本机内存块的快速访问并提高性能。
在开始工作之前,应使用Valve.Sockets.Library.Initialize();
功能。
工作完成后,使用Valve.Sockets.Library.Deinitialize();
功能。
NetworkingSockets server = new NetworkingSockets();uint pollGroup = server.CreatePollGroup();StatusCallback status = (ref StatusInfo info) => {switch (info.connectionInfo.state) {case ConnectionState.None:break;case ConnectionState.Connecting:server .AcceptConnection(info.connection);server.SetConnectionPollGroup(pollGroup, info.connection);break;case ConnectionState.Connected:Console.WriteLine("客户端已连接 - ID: " + info.connection + ", IP: " + info.connectionInfo.address.GetIP());break;case ConnectionState.ClosedByPeer:case ConnectionState.ProblemDetectedLocally:server .CloseConnection(info.connection);Console.WriteLine("客户端已断开连接 - ID: " + info.connection + ", IP: " + info.connectionInfo.address.GetIP());break;}};utils.SetStatusCallback(status);地址地址 = new Address();address.SetAddress("::0", port);uint ListenSocket = server.CreateListenSocket (参考地址);#if VALVESOCKETS_SPANMessageCallback message = (in NetworkingMessage netMessage) => {Console.WriteLine("从 - ID 收到的消息:" + netMessage.connection + ", 通道 ID: " + netMessage.channel + ", 数据长度: " + netMessage.length);};#else const int maxMessages = 20;NetworkingMessage[] netMessages = new NetworkingMessage[maxMessages];#endifwhile (!Console.KeyAvailable) {server.RunCallbacks(); #if VALVESOCKETS_SPANserver.ReceiveMessagesOnPollGroup(pollGroup, 消息, 20); #else int netMessagesCount = server.ReceiveMessagesOnPollGroup(pollGroup, netMessages, maxMessages);if (netMessagesCount > 0) {for (int i = 0; i < netMessagesCount; i++) {ref NetworkingMessage netMessage = ref netMessages[i];Console.WriteLine ("消息接收自 - ID: " + netMessage.connection + ", 通道 ID: " + netMessage.channel + ", Data长度: " + netMessage.length);netMessage.Destroy();}} #endif Thread.Sleep(15);}server.DestroyPollGroup(pollGroup);
NetworkingSockets 客户端 = new NetworkingSockets();uint 连接 = 0;StatusCallback 状态 = (ref StatusInfo info) => {switch (info.connectionInfo.state) {case ConnectionState.None:break;case ConnectionState.Connected:Console.WriteLine("客户端连接到服务器 - ID: " + connection);break;case ConnectionState.ClosedByPeer:case ConnectionState.ProblemDetectedLocally:client.CloseConnection(connection);Console.WriteLine("客户端与服务器断开连接");break;}};utils.SetStatusCallback(status);Address 地址 = new Address();address.SetAddress(":: 1", 端口);connection = client.Connect(参考地址);#if VALVESOCKETS_SPANMessageCallback message = (in NetworkingMessage netMessage) => {Console.WriteLine("从服务器收到的消息 - 通道 ID: " + netMessage.channel + ", 数据长度: " + netMessage.length);};#else const int maxMessages = 20;NetworkingMessage[] netMessages = new NetworkingMessage[ maxMessages];#endifwhile (!Console.KeyAvailable) {client.RunCallbacks(); #if VALVESOCKETS_SPANclient.ReceiveMessagesOnConnection(连接, 消息, 20); #else int netMessagesCount = client.ReceiveMessagesOnConnection(connection, netMessages, maxMessages);if (netMessagesCount > 0) {for (int i = 0; i < netMessagesCount; i++) {ref NetworkingMessage netMessage = ref netMessages[i];Console.WriteLine ("从服务器收到的消息 - 通道 ID: " + netMessage.channel + ", 数据长度: " + netMessage.length);netMessage.Destroy();}} #endif Thread.Sleep(15);}
byte[] data = new byte[64];sockets.SendMessageToConnection(连接, 数据);
byte[] buffer = new byte[1024];netMessage.CopyTo(buffer);
DebugCallback debug = (type, message) => {Console.WriteLine("调试-类型:" + type + ",消息:" + message);};NetworkingUtils utils = new NetworkingUtils();utils.SetDebugCallback(DebugType.Everything , 调试);
使用方法与.NET环境下几乎相同,只是控制台功能必须替换为Unity提供的功能。如果将在游戏循环中调用NetworkingSockets.RunCallbacks()
,则通过在播放器设置中启用适当的选项来保持 Unity 在后台运行。
NetworkingSockets.SendMessageToConnection()
函数的标志定义:
SendFlags.Unreliable
不可靠,无法保证消息的传递,消息可能会乱序传递。
SendFlags.Reliable
可靠有序,目标连接必须接收消息,并且应尝试重新发送,直到消息被传递为止。
SendFlags.NoNagle
消息不会与计时器内的其他消息分组。
SendFlags.NoDelay
如果消息不能相对快速地发送,则不会缓冲该消息。
NetworkingIdentity
结构的身份类型定义:
IdentityType.Invalid
未知或无效。
IdentityType.SteamID
Steam 标识符。
IdentityType.IPAddress
IPv4/IPv6 地址。
ConnectionInfo.state
字段的连接状态定义:
ConnectionState.None
虚拟状态,连接不存在或已关闭。
ConnectionState.Connecting
正在进行中,由NetworkingSockets.Connect()
函数启动建立连接。
ConnectionState.FindingRoute
如果服务器接受该连接,则此连接切换到会合状态,但端到端的路由仍然尚未建立(通过中继网络)。
ConnectionState.Connected
由NetworkingSockets.Connect()
函数发起的连接请求已完成。
ConnectionState.ClosedByPeer
连接已被对等方关闭,但未在本地关闭。如果入站队列中有任何消息,则可以检索它们。否则,除了使用NetworkingSockets.CloseConnection()
函数关闭连接之外,无法对连接执行任何操作。从 API 角度来看,连接仍然存在,必须关闭以释放资源。
ConnectionState.ProblemDetectedLocally
本地检测到连接中断。尝试发送更多消息将会失败。队列中所有剩余的已接收消息均可用。从 API 角度来看,连接仍然存在,必须关闭以释放资源。
配置范围定义:
ConfigurationScope.Global
ConfigurationScope.SocketsInterface
ConfigurationScope.ListenSocket
ConfigurationScope.Connection
配置数据类型的定义:
ConfigurationDataType.Int32
ConfigurationDataType.Int64
ConfigurationDataType.Float
ConfigurationDataType.String
ConfigurationDataType.FunctionPtr
配置值的定义:
ConfigurationValue.Invalid
ConfigurationValue.FakePacketLossSend
ConfigurationValue.FakePacketLossRecv
ConfigurationValue.FakePacketLagSend
ConfigurationValue.FakePacketLagRecv
ConfigurationValue.FakePacketReorderSend
ConfigurationValue.FakePacketReorderRecv
ConfigurationValue.FakePacketReorderTime
ConfigurationValue.FakePacketDupSend
ConfigurationValue.FakePacketDupRecv
ConfigurationValue.FakePacketDupTimeMax
ConfigurationValue.TimeoutInitial
ConfigurationValue.TimeoutConnected
ConfigurationValue.SendBufferSize
ConfigurationValue.SendRateMin
ConfigurationValue.SendRateMax
ConfigurationValue.NagleTime
ConfigurationValue.IPAllowWithoutAuth
ConfigurationValue.MTUPacketSize
ConfigurationValue.MTUDataSize
ConfigurationValue.Unencrypted
ConfigurationValue.EnumerateDevVars
ConfigurationValue.SymmetricConnect
ConfigurationValue.LocalVirtualPort
ConfigurationValue.ConnectionStatusChanged
ConfigurationValue.AuthStatusChanged
ConfigurationValue.RelayNetworkStatusChanged
ConfigurationValue.MessagesSessionRequest
ConfigurationValue.MessagesSessionFailed
ConfigurationValue.P2PSTUNServerList
ConfigurationValue.P2PTransportICEEnable
ConfigurationValue.P2PTransportICEPenalty
ConfigurationValue.P2PTransportSDRPenalty
ConfigurationValue.SDRClientConsecutitivePingTimeoutsFailInitial
ConfigurationValue.SDRClientConsecutitivePingTimeoutsFail
ConfigurationValue.SDRClientMinPingsBeforePingAccurate
ConfigurationValue.SDRClientSingleSocket
ConfigurationValue.SDRClientForceRelayCluster
ConfigurationValue.SDRClientDebugTicketAddress
ConfigurationValue.SDRClientForceProxyAddr
ConfigurationValue.SDRClientFakeClusterPing
ConfigurationValue.LogLevelAckRTT
ConfigurationValue.LogLevelPacketDecode
ConfigurationValue.LogLevelMessage
ConfigurationValue.LogLevelPacketGaps
ConfigurationValue.LogLevelP2PRendezvous
ConfigurationValue.LogLevelSDRRelayPings
配置值结果定义:
ConfigurationValueResult.BadValue
ConfigurationValueResult.BadScopeObject
ConfigurationValueResult.BufferTooSmall
ConfigurationValueResult.OK
ConfigurationValueResult.OKInherited
调试类型的定义:
DebugType.None
DebugType.Bug
DebugType.Error
DebugType.Important
DebugType.Warning
DebugType.Message
DebugType.Verbose
DebugType.Debug
DebugType.Everything
运算结果定义:
Result.OK
成功.
Result.Fail
一般失败。
Result.NoConnection
网络连接失败。
Result.InvalidParam
参数不正确。
Result.InvalidState
调用的对象处于无效状态。
Result.Ignored
目标正在忽略发件人。
提供每个套接字事件。
StatusCallback(ref StatusInfo info)
在侦听套接字上的调度机制返回连接状态时发出通知。应保留对委托的引用,以免被垃圾收集。
提供每个应用程序的事件。
DebugCallback(DebugType type, string message)
在出现具有所需详细程度的调试信息时发出通知。应保留对委托的引用,以免被垃圾收集。
包含带有 IP 地址和端口号的编组数据。
Address.ip
IP 地址(以字节为单位)。
Address.port
端口号。
Address.IsLocalHost
检查身份是否为 localhost。
Address.GetIP()
以可打印的形式获取 IP 地址。
Address.SetLocalHost(ushort port)
将 localhost 设置为指定端口。
Address.SetAddress(string ip, ushort port)
设置具有指定端口的 IP 地址 (IPv4/IPv6)。
Address.Equals(Address other)
确定地址相等。
包含带有配置的编组数据。
Configuration.value
是ConfigurationValue
枚举中描述的值的类型。
Configuration.dataType
ConfigurationDataType
枚举中描述的数据类型。
Configuration.data
配置数据的联合。
包含带有连接状态的编组数据。
StatusInfo.connection
连接 ID。
StatusInfo.connectionInfo
本质上是具有编组数据的ConnectionInfo
结构。
包含带有连接信息的编组数据。
ConnectionInfo.identity
端点的标识符。
ConnectionInfo.userData
用户提供的数据,使用NetworkingSockets.SetConnectionUserData()
函数设置。
ConnectionInfo.listenSocket
侦听此连接的套接字。
ConnectionInfo.address
端点的远程地址。
ConnectionInfo.state
ConnectionState
枚举中描述的连接的高级状态。
ConnectionInfo.endReason
连接终止或问题的基本原因。
ConnectionInfo.endDebug
以人类可读的形式解释连接终止或问题。这仅用于调试诊断目的,而不是向用户显示。它可能包含一些特定于该问题的详细信息。
ConnectionInfo.connectionDescription
调试描述包括连接句柄、连接类型和对等信息。
包含带有频繁请求的连接状态的编组数据。
ConnectionStatus.state
ConnectionState
枚举中描述的连接的高级状态。
ConnectionStatus.ping
当前 ping(以毫秒为单位)。
ConnectionStatus.connectionQualityLocal
在本地测量的连接质量(按顺序端到端传送的数据包的百分比)。
ConnectionStatus.connectionQualityRemote
从远程主机观察到的远程数据包传送成功率。
ConnectionStatus.outPacketsPerSecond
最近历史记录中的当前出站数据包速率。
ConnectionStatus.outBytesPerSecond
最近历史记录中的当前出站数据速率。
ConnectionStatus.inPacketsPerSecond
最近历史记录中的当前入站数据包速率。
ConnectionStatus.inBytesPerSecond
最近历史记录中的当前入站数据速率。
ConnectionStatus.sendRateBytesPerSecond
估计数据发送到对等点的速率。它可能明显高于ConnectionStatus.outBytesPerSecond
,这意味着通道的容量高于发送的数据。
ConnectionStatus.pendingUnreliable
等待不可靠发送的字节数。这是最近请求发送但尚未实际发送的数据。
ConnectionStatus.pendingReliable
待可靠发送的字节数。可靠的数字还包括之前在线传输但现在已安排重新传输的数据。因此,即使在检查之间没有调用发送可靠数据,也可以观察到两次检查之间字节的增加。等待 Nagle 延迟的数据将出现在这些数字中。
ConnectionStatus.sentUnackedReliable
已连接到线路但尚未收到确认,因此可能需要重新传输的可靠数据的字节数。
包含网络身份的编组数据。
NetworkingIdentity.type
网络身份的描述。
NetworkingIdentity.IsInvalid
检查身份是否具有无效类型。
NetworkingIdentity.GetSteamID()
获取 Steam ID。
NetworkingIdentity.SetSteamID(ulong steamID)
设置 Steam ID。
包含网络消息的编组数据。
NetworkingMessage.identity
发送者的标识符。
NetworkingMessage.connectionUserData
用户提供的使用NetworkingSockets.SetConnectionUserData()
函数设置的连接数据。
NetworkingMessage.timeReceived
接收消息时的本地时间戳。
NetworkingMessage.messageNumber
发送者分配的消息号。
NetworkingMessage.data
消息的有效负载。
NetworkingMessage.length
有效负载的长度。
NetworkingMessage.connection
消息来自的连接 ID。
NetworkingMessage.channel
接收消息的通道号。
NetworkingMessage.flags
用于发送消息的标志。
NetworkingMessage.CopyTo(byte[] destination)
将有效负载从消息复制到目标数组。
NetworkingMessage.Destroy()
销毁消息。仅当从套接字获取消息时才应调用。
包含指向套接字的托管指针。
NetworkingSockets.CreateListenSocket(ref Address address, Configuration[] configurations)
创建一个具有可选配置的套接字,并返回一个套接字ID,该ID侦听由NetworkingSockets.Connect()
函数发起的传入连接。
NetworkingSockets.Connect(ref Address address, Configuration[] configurations)
使用可选配置启动与外部主机的连接。返回本地连接 ID。
NetworkingSockets.AcceptConnection(Connection connection)
接受在侦听套接字上接收到的传入连接。当收到连接尝试时(可能在交换了一些基本的握手数据包以防止简单的欺骗之后),将在ConnectionState.Connecting
状态下创建一个连接接口对象,并调用StatusCallback()
。返回Result
枚举中描述的结果。
NetworkingSockets.CloseConnection(Connection connection, int reason, string debug, bool enableLinger)
与主机断开连接并使连接句柄无效。连接上任何未读的数据都将被丢弃。 Reason 参数是一个可选的用户提供的代码,该代码将在另一端接收并记录在后端分析中(如果可能)。如果原因代码超出可接受的范围,调试日志记录可能会指示错误。调试参数是一个可选的人类可读的诊断字符串,将在另一端接收并在后端分析中记录(如果可能)。如果用户希望将套接字置于延迟状态,并尝试刷新任何剩余的已发送数据,则应启用延迟参数,否则不会刷新可靠的数据。如果连接已经结束,则忽略原因代码、调试字符串和 linger 参数。成功时返回 true,失败时返回 false。
NetworkingSockets.CloseListenSocket(ListenSocket socket, string remoteReason)
销毁侦听套接字以及通过在侦听套接字上接受连接而生成的所有客户端套接字。远程原因决定了对被破坏的客户端套接字执行哪些清理操作。如果请求清理并且用户已请求绑定到特定本地端口的监听套接字以促进直接 IPv4 连接,则底层 UDP 套接字必须保持打开状态,直到所有客户端都被清理。成功时返回 true,失败时返回 false。
NetworkingSockets.SetConnectionUserData(Connection peer, long userData)
设置用户为连接提供的数据。成功时返回 true,失败时返回 false。
NetworkingSockets.GetConnectionUserData(Connection peer)
返回用户提供的数据,如果句柄无效或尚未为连接设置任何数据,则返回 -1。
NetworkingSockets.SetConnectionName(Connection peer, string name)
设置连接的名称,主要用于调试。
NetworkingSockets.GetConnectionName(Connection peer, StringBuilder name, int maxLength)
将连接名称获取到可变字符串。成功时返回 true,失败时返回 false。
NetworkingSockets.SendMessageToConnection(Connection connection, byte[] data, int length, SendFlags flags)
将消息发送到已连接套接字上的主机。长度和发送类型参数是可选的。可以一次指定多个标志。返回Result
枚举中描述的结果。可以使用指向本机缓冲区的指针IntPtr
来代替对字节数组的引用。
NetworkingSockets.FlushMessagesOnConnection(Connection connection)
如果 Nagle 已启用(默认情况下启用),则消息将在发送前排队 Nagle 时间,以将小消息合并到同一个数据包中。调用此函数可刷新任何排队的消息并在下一次传输时立即发送它们。返回Result
枚举中描述的结果。
NetworkingSockets.ReceiveMessagesOnConnection(Connection connection, NetworkingMessage[] messages, int maxMessages)
从连接的套接字中获取下一条可用消息。返回一些消息,如果连接句柄无效,则返回 -1。数组中返回的消息的顺序是相关的。可靠的消息将按照发送的顺序接收。如果获得任何消息,则应为每条消息调用message.Destroy()
以释放资源。
NetworkingSockets.GetConnectionInfo(Connection connection, ref ConnectionInfo info)
获取有关指定连接的信息。成功时返回 true,失败时返回 false。
NetworkingSockets.GetQuickConnectionStatus(Connection connection, ref ConnectionStatus status)
获取一组简短的连接状态,可以在游戏中向用户显示。成功时返回 true,失败时返回 false。
NetworkingSockets.GetDetailedConnectionStatus(Connection connection, StringBuilder status, int statusLength)
以可打印的形式获取详细的连接统计信息。成功时返回 0,失败时返回 -1,如果可变字符串的容量不够,则返回 > 0。
NetworkingSockets.GetListenSocketAddress(ListenSocket socket, ref Address address)
获取侦听套接字的本地 IP 和端口号。成功时返回 true,失败时返回 false。
NetworkingSockets.CreateSocketPair(Connection connectionLeft, Connection connectionRight, bool useNetworkLoopback, ref NetworkingIdentity identityLeft, ref NetworkingIdentity identityRight)
创建一对相互通信的连接,例如环回通信。两个连接将立即进入连接状态,并且不会调用任何回调。此后,如果任一连接关闭,另一个连接将收到回调,就像它们通过网络进行通信一样。默认情况下,使用内部缓冲区,完全绕过网络,将消息切分成数据包,加密,复制有效负载等。这意味着环回数据包默认情况下不会模拟滞后或丢失。启用网络环回参数将导致套接字对通过临时端口上的本地网络环回设备发送数据包。这种情况下支持假滞后和假丢失,并且CPU时间花费在加密和解密上。
NetworkingSockets.GetIdentity()
获取与套接字关联的身份。
NetworkingSockets.CreatePollGroup()
为连接创建一个新的轮询组。返回轮询组句柄。
NetworkingSockets.DestroyPollGroup(PollGroup pollGroup)
销毁轮询组。如果轮询组中有任何连接,它们将从组中删除,并处于不属于任何轮询组的状态。如果传递了无效的轮询组句柄,则返回 false。
NetworkingSockets.SetConnectionPollGroup(PollGroup pollGroup, Connection connection)
将连接分配给轮询组。一个连接可能只属于一个轮询组。将连接添加到轮询组会隐式地将其从任何其他轮询组中删除。您可以将零值传递给轮询组参数以从当前轮询组中删除连接。如果连接上当前有待处理的已接收消息,则会尝试将它们添加到轮询组的消息队列中,其顺序大致与连接在该连接已是轮询组的一部分时所应用的顺序相同。收到消息。如果连接句柄无效或轮询组句柄无效,则返回 false。
NetworkingSockets.ReceiveMessagesOnPollGroup()
从轮询组中任何连接上的套接字获取下一条可用消息。检查NetworkingMessage.connection
以识别连接。不同连接之间的消息传递顺序通常与完成消息的最后一个数据包的接收顺序相匹配。但这并不是一个强有力的保证,特别是对于将连接分配给轮询组时正确接收的数据包。同一连接上的消息传递顺序已明确定义,并且存在相同的保证。消息不按连接分组,因此它们不一定连续出现在列表中,它们可能与其他连接的消息交错。返回一些消息,如果轮询组句柄无效,则返回 -1。
NetworkingSockets.RunCallbacks()
调度回调(如果可用)。
NetworkingUtils.Dispose()
销毁网络实用程序并清理非托管资源。
NetworkingUtils.Time
返回当前本地单调时间(以微秒为单位)。当应用程序保持活动状态时,它永远不会重置。
NetworkingUtils.FirstConfigurationValue
获取当前环境中可用的最小编号配置值。
NetworkingUtils.SetStatusCallback(StatusCallback callback)
设置连接状态更新的回调。成功时返回 true,失败时返回 false。
NetworkingUtils.SetDebugCallback(DebugType detailLevel, DebugCallback callback)
设置调试输出的回调。
NetworkingUtils.SetConfigurationValue(ConfigurationValue configurationValue, ConfigurationScope configurationScope, IntPtr scopeObject, ConfigurationDataType dataType, IntPtr value)
根据ConfigurationValue
、 ConfigurationScope
和ConfigurationDataType
枚举设置配置值。 value 参数应该是对实际值的引用。
NetworkingUtils.SetConfigurationValue(Configuration configuration, ConfigurationScope configurationScope, IntPtr scopeObject)
根据ConfigurationScope
枚举使用Configuration
结构设置配置。
NetworkingUtils.GetConfigurationValue(ConfigurationValue configurationValue, ConfigurationScope configurationScope, IntPtr scopeObject, ref ConfigurationDataType dataType, ref IntPtr result, ref IntPtr resultLength)
根据ConfigurationValue
、 ConfigurationScope
和ConfigurationDataType
枚举获取配置值。
包含常量字段。
Library.maxCloseMessageLength
连接关闭时原因字符串的最大长度(以字节为单位)。
Library.maxMessageSize
可以发送的单个消息的最大大小。
Library.Initialize(ref NetworkingIdentity identity, StringBuilder errorMessage)
将与套接字关联的可选标识初始化本机库。错误消息参数是可选的,应用于确定初始化期间的错误。错误消息的可变字符串的容量必须等于Library.maxErrorMessageLength
。
Library.Deinitialize()
取消初始化本机库。工作完成后应调用。