Documentación de Steamworks
steamnetworkingtypes.h
Varios tipos y funciones utilizadas por las API de red.

Describiendo hosts de red


Tipos necesarios para describir hosts de red.

enumeración ESteamNetworkingIdentityType

Diferentes tipos de identidades que puede tener un host remoto. La mayoría de las veces en Steam, este será un CSteamID. Sin embargo, en algunos casos puede deshabilitar la autenticación, en cuyo caso se utilizará una identidad más genérica.

enum ESteamNetworkingIdentityType { // Dummy/unknown/invalid k_ESteamNetworkingIdentityType_Invalid = 0, // // Identificadores básicos específicos de la plataforma. // k_ESteamNetworkingIdentityType_SteamID = 16, // 64-bit CSteamID // // Identificadores especiales. // // Usa tu dirección IP (y puerto) como tu "identidad". // Estos tipos de identidades son siempre no autenticados. // Son útiles para portar código de sockets simples, y otras // situaciones en las que no te importa la autenticación. En este // caso, La identidad local será "localhost", // y la dirección remota será tu dirección de red. // // Usamos el mismo tipo para IPv4 o IPv6, y // la dirección siempre se guarda como IPv6. Usamos IPv4 // direcciones mapeadas para manejar IPv4. k_ESteamNetworkingIdentityType_IPAddress = 1, // Cadena genérica / blobs binarios. Depende de tu aplicación interpretar esto. // Esta biblioteca te puede decir si el host remoto presentó un certificado // firmado por alguien que has elegido para confiar, con esta identidad en él. // Depende de ti decidir en última instancia qué significa esta identidad. k_ESteamNetworkingIdentityType_GenericString = 2, k_ESteamNetworkingIdentityType_GenericBytes = 3, // Asegúrate de que esta enumeración se almacena en un int. k_ESteamNetworkingIdentityType__Force32bit = 0x7fffffff, }}

struct SteamNetworkingIdentity


Una forma abstracta de representar la identidad de un host de red.

struct SteamNetworkingIdentity { /// Tipo de identidad. ESteamNetworkingIdentityType m_eType; // // Get/Set en varios formatos. // void Clear(); bool IsInvalid() const; // Devuelve true si somos del tipo inválido. No realiza ninguna otra verificación de validez (por ejemplo, es SteamID realmente válido) void SetSteamID( CSteamID steamID ); CSteamID GetSteamID() const; // Devuelve negro CSteamID (!IsValid()) si la identidad no es un SteamID void SetSteamID64( uint64 steamID ); // Toma SteamID como un número de 64 bits en bruto uint64 GetSteamID64() const; // Devuelve 0 si la identidad no es SteamID void SetIPAddr( const SteamNetworkingIPAddr &addr ); // Establece un IP:port específicado const SteamNetworkingIPAddr *GetIPAddr() const; // devuelve null si no somos una dirección. // "localhost" es equivalente para muchos fines "anónimos." Nuestro control remoto // nos identificará por la dirección de red que usamos. void SetLocalHost(); // Establecer en localhost. (Siempre usamos IPv6 ::1 para esto, no 127.0.0.1) bool IsLocalHost() const; // Devuelve true si esta identidad es localhost. bool SetGenericString( const char *pszString ); // Devuelve false si la longitud no es válida const char *GetGenericString() const; // Devuelve nullptr si no es el tipo de cadena genérica bool SetGenericBytes( const void *data, size_t cbLen ); // Devuelve false si el tamaño no es válido. const uint8 *GetGenericBytes( int &cbLen ) const; // Devuelve null si no es un tipo de bytes genérico /// Ver si dos identidades son idénticas bool operator==(const SteamNetworkingIdentity &x ) const; /// Imprimir en una cadena legible por personas. Esto es adecuado para mensajes de depuración /// o en cualquier otro momento que necesites para codificar la identidad como una cadena. Tiene un /// Formato tipo URL (type:<type-data>). Tu búfer debe ser al menos /// k_cchMaxString bytes grandes para evitar el truncamiento void ToString( char *buf, size_t cbBuf ) const; /// Volver a analizar una cadena que se generó usandoToString bool ParseString( const char *pszStr ); // Max sizes enum { k_cchMaxString = 128, // Longitud máxima del búfer necesaria para mantener cualquier identidad, formateada en formato de cadena por ToString k_cchMaxGenericString = 32, // Longitud máxima de la cadena para identidades de cadena genéricas. Incluyendo la terminación '\0' k_cbMaxGenericBytes = 32, }; // [] };

struct SteamNetworkingIPAddr


Almacenar una IP y un puerto.

Siempre se utiliza IPv6; IPv4 se representa mediante "IPv4-mapped" con las direcciones: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd. (Consulta RFC 4291 section 2.5.5.2.)
struct SteamNetworkingIPAddr { void Clear(); // Poner todo a cero. P.ej. [::]:0 bool IsIPv6AllZeros() const; // Devuelve true si la IP es ::0. (No comprueba el puerto). void SetIPv6( const uint8 *ipv6, uint16 nPort ); // Establecer dirección IPv6. IP se interpreta como bytes, por lo que no hay problemas de endian. (Igual que inaddr_in6.) La IP puede ser una dirección IPv4 asignada void SetIPv4( uint32 nIP, uint16 nPort ); // Establece a la dirección asignada de IPv4. La IP y el puerto están en orden de bytes del host. bool IsIPv4() const; // Devuelve true si la IP está asignada a IPv4 uint32 GetIPv4() const; // Devuelve la IP en orden de bytes del host (por ejemplo, aa.bb.cc.dd como 0xaabbccdd). Devuelve 0 si IP no está asignada IPv4. void SetIPv6LocalHost( uint16 nPort = 0); // Establece la dirección de host local de IPv6 :: 1, y el puerto especificado. bool IsLocalHost() const; // Devuelve true si esta identidad es localhost. (O bien IPv6 ::1, or IPv4 127.0.0.1) // La longitud máxima del búfer necesario para mantener el IP formateado mediante ToString, incluido '\0' // ([0123:4567:89ab:cdef:0123:4567:89ab:cdef]:12345) enum { k_cchMaxString = 48 }; /// Imprimir en una cadena, con o sin el puerto. Las direcciones IPv4 asignadas se imprimen /// como punto decimal (12.34.56.78), de lo contrario, imprimirá la forma canónica /// se formula siguiendo el estándar RFC 5952. Si incluyes el puerto, IPv6 estarás rodeado por /// corchetes, por ejemplo [::1:2]:80. Tu búfer debe tener al menos k_cchMaxString bytes /// para evitar el truncamiento inString void en línea ( char *buf, size_t cbBuf, bool bWithPort ) const; /// Analizar una dirección IP y un puerto opcional. Si un puerto no está presente, se establece en 0. /// (Esto significa que no se puede saber si se especificó explícitamente un puerto cero). en línea bool ParseString( const char *pszStr ); union { uint8 m_ipv6[]; struct // IPv4 "dirección asignada" (rfc4038 section 4.2) { uint64 m_8zeros; uint16 m_0000; uint16 m_ffff; uint8 m_ip[]; // NOTA: Como bytes, es decir, orden de bytes de red } m_ipv4; }; uint16 m_port; // Host byte order /// Ver si dos direcciones son idénticas bool operator==(const SteamNetworkingIPAddr &x ) const; };

Estado de conexión

Estos tipos se utilizan para describir el estado de una conexión. Consulta ISteamnetworkingSockets::GetConnectionInfo, SteamNetConnectionStatusChangedCallback_t

Enumeración ESteamNetworkingState

Enumera estados de conexión de alto nivel.

enumeración ESteamNetworkingConnectionState { /// Valor ficticio utilizado para indicar una condición de error en la API. /// La conexión especificada no existe o ya se ha cerrado. k_ESteamNetworkingConnectionState_None = 0, /// Estamos tratando de establecer si los compañeros pueden hablar entre ellos, /// si QUIEREN hablar entre ellos, realizar una autenticación básica, /// e intercambiar claves de encriptación. /// /// - Para conexiones en el lado del "cliente" (iniciado localmente): /// Estamos en el proceso de intentar establecer una conexión. /// Según el tipo de conexión, es posible que no sepamos quiénes son. /// Ten en cuenta que no es posible saber si estamos esperando en /// red para completar los paquetes de intercambio, o para la capa de aplicación /// para aceptar la conexión. /// /// - Para conexiones en el lado del "servidor" (aceptado a través del conector de escucha): /// Hemos completado un saludo básico y el cliente ha presentado /// alguna prueba de identidad. La conexión está lista para ser aceptada /// utilizando AcceptConnection(). /// /// En cualquier caso, cualquier paquete no confiable enviado ahora es casi seguro /// para ser dejado. Se garantiza que los intentos de recibir paquetes fallarán. /// Puedes enviar mensajes si el modo de envío permite que se pongan en cola. /// pero si cierra la conexión antes de que la conexión sea realmente /// establecido, cualquier mensaje en cola se descartará inmediatamente. /// (No intentaremos vaciar la cola y confirmar la entrega a /// un host remoto, que normalmente ocurre cuando se cierra una conexión). k_ESteamNetworkingConnectionState_Connecting = 1, /// Algunos tipos de conexión usan un canal trasero o una tercera parte confiable /// para la primera comunicación. Si el servidor acepta la conexión, /// entonces estas conexiones cambian al estado de encuentro. Durante este /// estado, todavía no hemos establecido una ruta de extremo a extremo (a través de /// la red de retransmisión), y si envía algún mensaje no confiable, /// serán descartados k_ESteamNetworkingConnectionState_FindingRoute = 2, /// Hemos recibido comunicaciones de nuestros pares (y sabemos /// quienes son) y son todos buenos. Si cierra la conexión ahora, /// haremos nuestro mejor esfuerzo para eliminar cualquier dato confiable enviado que /// no ha sido reconocido por el par. (Pero ten en cuenta que esto sucede /// desde dentro del proceso de solicitud, por lo que a diferencia de una conexión TCP, /// no le entregas el proceso totalmente al sistema operativo para que lo maneje). k_ESteamNetworkingConnectionState_Connected = 3, /// La conexión ha sido cerrada por nuestro par, pero no se ha cerrado localmente. /// La conexión todavía existe desde la perspectiva de la API. Debes cerrar el /// handle para liberar recursos. Si hay algún mensaje en la cola de entrada, /// puedes recuperarlos. De lo contrario, no se puede hacer nada con la conexión /// excepto para cerrarlo. /// /// Esta estadística es similar a CLOSE_WAIT en la máquina de estado TCP. k_ESteamNetworkingConnectionState_ClosedByPeer = 4, /// Se ha detectado localmente una interrupción en la conexión. (Por ejemplo, tiempo de espera, /// conexión de internet local interrumpida, etc.) /// /// La conexión todavía existe desde una perspectiva API. Debes cerrar el /// handle para liberar recursos /// /// Los intentos de enviar más mensajes fallarán. Cualquier mensaje restante recibido /// en la cola están disponibles. k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, // // Los siguientes valores se usan internamente y no serán devueltos por ninguna API. // Los documentamos aquí para proporcionar una pequeña perspectiva de la máquina de estado que se utiliza // debajo de la cubierta. // /// Nos hemos desconectado de nuestro lado, y desde una perspectiva de API, la conexión está cerrada. /// No se pueden enviar ni recibir más datos. Se han vaciado todos los datos confiables, o bien /// los hemos parado y los hemos descartado. Aún no sabemos con certeza que el par sepa /// que la conexión se ha cerrado, sin embargo, solo estamos dando vueltas para que si lo hacemos /// obtener un paquete de ellos, podemos enviarles los paquetes apropiados para que puedan /// saber por qué se cerró la conexión (y no tener que depender de un tiempo de espera, lo que hace que /// aparezca como si algo estuviera mal). k_ESteamNetworkingConnectionState_FinWait = -1, /// Nos hemos desconectado de nuestro lado, y desde una perspectiva de API, la conexión está cerrada. /// No se pueden enviar ni recibir más datos. Desde una perspectiva de red, sin embargo, en el cable, /// todavía no hemos dado ninguna indicación al interlocutor de que la conexión está cerrada. /// Estamos en el proceso de vaciar el último bit de datos confiables. Una vez hecho esto, /// le informaremos al interlocutor que la conexión se ha cerrado, y la transición a el /// estado FinWait. /// /// Ten en cuenta que no se da ninguna indicación al host remoto de que hayamos cerrado la conexión, /// hasta que los datos hayan sido vaciados. Si el host remoto intenta enviarnos datos, /// haz lo que sea necesario para mantener la conexión activa hasta que se pueda cerrar correctamente. /// Pero, de hecho, los datos se descartarán, ya que no hay forma de que la aplicación /// leerlo de nuevo. Normalmente, esto no es un problema, ya que los protocolos de aplicación que utiliza /// la funcionalidad persistente está diseñada para que el host remoto espere la respuesta /// antes de enviar más datos. k_ESteamNetworkingConnectionState_Linger = -2, /// La conexión está completamente inactiva y lista para ser destruida k_ESteamNetworkingConnectionState_Dead = -3, k_ESteamNetworkingConnectionState__Force32Bit = 0x7fffffff };

Enumeración ESteamNetConnectionEnd


Enumerar varias causas por la finalización de la conexión. Estas están diseñadas para funcionar de manera similar a los códigos de error HTTP: el rango numérico le brinda una clasificación aproximada en cuanto a la fuente del problema.
enumeración ESteamNetConnectionEnd { // Valor inválido / centinela k_ESteamNetConnectionEnd_Invalid = 0, // // Códigos de aplicación. Estos son los valores que pasará a // ISteamNetworkingSockets::CloseConnection. Puedes utilizar estos códigos si // deseas realizar un sondeo a través de códigos de razón específicos de la aplicación. Si no lo haces // necesitas esta habilidad, siéntete libre de pasar siempre // k_ESteamNetConnectionEnd_App_Generic. // // La distinción entre "normal" y "excepcional" la terminación es // una que puedes usar si lo encuentras útil, pero no es necesario para ti // hacerlo. El único lugar donde distinguimos entre normal y // excepcional está en el análisis de conexión. Si es significativo, // la proporción de conexiones termina de manera excepcional, // esto puede activar una alerta. // // 1xxx: la aplicación finalizó la conexión de forma "habitual". // Por ejemplo: un usuario desconectado intencionalmente del servidor, // el juego terminó normalmente, etc. k_ESteamNetConnectionEnd_App_Min = 1000, k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min, // Usar códigos en este rango para desconexión "normal" k_ESteamNetConnectionEnd_App_Max = 1999, // 2xxx: la aplicación terminó la conexión en algún tipo de excepcional // o una forma inusual que pueda indicar un error o un problema // de configuración. // k_ESteamNetConnectionEnd_AppException_Min = 2000, k_ESteamNetConnectionEnd_AppException_Generic = k_ESteamNetConnectionEnd_AppException_Min, // Usar códigos en este rango para desconexión "inusual" k_ESteamNetConnectionEnd_AppException_Max = 2999, // // Códigos del sistema. Estos serán devueltos por el sistema cuando // el estado de la conexión es k_ESteamNetworkingConnectionState_ClosedByPeer // o k_ESteamNetworkingConnectionState_ProblemDetectedLocally. Es // ilegal pasar un código en este rango a ISteamNetworkingSockets::CloseConnection // // 3xxx: la conexión falló o finalizó debido a un problema con // con el host local o su conexión a Internet. k_ESteamNetConnectionEnd_Local_Min = 3000, // No puedes hacer lo que quieres hacer porque se está ejecutando en modo fuera de línea. k_ESteamNetConnectionEnd_Local_OfflineMode = 3001, // Tenemos problemas para contactar con muchos (quizás todos) los relés. // Dado que es poco probable que todos se desconecten a la vez, la mejor // explicación es que tenemos un problema en nuestro final. Ten en cuenta que no nos // molesta distinguir entre "muchos" y "todos", porque en la práctica, // lleva tiempo detectar un problema de conexión, y por el momento // la conexión ha caducado, es posible que no hayamos podido // probar activamente todos los grupos de retransmisión, incluso si pudiéramos // contactarlos a la vez. Entonces este código solo significa que: // // * No tenemos ninguna comunicación reciente exitosa con ningún relé. // * Tenemos evidencia de fallos recientes para comunicarnos con múltiples relés. k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, // Un servidor alojado tiene problemas para hablar con el relé // que el cliente estaba usando, por lo que es muy probable que el problema esté // en nuestro lado k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, // No podemos obtener la configuración de la red. Esto es // *casi* siempre un problema local, ya que la configuración de red // proviene de la CDN, que es bastante confiable. k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, // Steam rechazó nuestra solicitud porque no tenemos derechos // para hacer esto. k_ESteamNetConnectionEnd_Local_Rights = 3005, k_ESteamNetConnectionEnd_Local_Max = 3999, // 4xxx: la conexión falló o terminó, y parece que la // causa NO tiene que ver con el host local o tu // conexión a internet. Podría ser causado por el // host remoto, o podría estar en algún punto intermedio. k_ESteamNetConnectionEnd_Remote_Min = 4000, // Se perdió la conexión, y por lo que podemos decir nuestra conexión // a servicios relevantes (relés) no ha sido interrumpida. Esto no // significa que el problema sea "tu culpa", solo significa que no // parece que tenemos problemas de red en nuestro extremo. k_ESteamNetConnectionEnd_Remote_Timeout = 4001, // Algo no era válido con el certificado o protocolo de enlace de cifrado // de la información que me diste, no entiendo o no me gustan tus tipos de claves // etc. k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, // Me presentaste un certificado que pude analizar // y *técnicamente* podríamos utilizar una comunicación cifrada. // Pero hubo un problema que me impide verificar tu identidad // o asegurarse de que alguien en el medio no pueda observar nuestra comunicación. // por ejemplo: - faltaba la clave de CA (y no acepto certificados sin firmar) // - La clave de CA no es una en la que confío, // - El certificado no fue restringido apropiadamente por aplicación, usuario, tiempo, centro de datos, etc. // - El certificado no fue emitido para ti. // - etc. k_ESteamNetConnectionEnd_Remote_BadCert = 4003, // No pudimos reunirnos con el host remoto porque // no están registrados en Steam k_ESteamNetConnectionEnd_Remote_NotLoggedIn = 4004, // No pudimos reunirnos con el host remoto porque // no están ejecutando la aplicación correcta. k_ESteamNetConnectionEnd_Remote_NotRunningApp = 4005, // Algo está mal con la versión del protocolo que estás utilizando. // (Probablemente el código que estás ejecutando es demasiado antiguo). k_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, k_ESteamNetConnectionEnd_Remote_Max = 4999, // 5xxx: la conexión falló por alguna otra razón. k_ESteamNetConnectionEnd_Misc_Min = 5000, // Un error que no es necesariamente el resultado de un error de software, // pero eso debería suceder raramente para que no valga específicamente // escribiendo UI o haciendo creando un mensaje localizado. // La cadena de depuración debe contener más detalles k_ESteamNetConnectionEnd_Misc_Generic = 5001, // Fallo genérico que probablemente sea un error de software. k_ESteamNetConnectionEnd_Misc_InternalError = 5002, // Se agotó el tiempo de espera para la conexión con el host remoto, pero // no sé si el problema está en nuestro extremo, en el medio, // o en tu extremo. k_ESteamNetConnectionEnd_Misc_Timeout = 5003, // Tenemos problemas para comunicarnos con el relé relevante. // No tenemos suficiente información para decir si // el problema está en nuestro extremo o no. k_ESteamNetConnectionEnd_Misc_RelayConnectivity = 5004, // Hay algunos problemas para comunicarse con Steam. k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, // Un servidor en una situación de alojamiento dedicado y no tiene sesiones de retransmisión // activa con los que contestar a un cliente. (Es responsabilidad del cliente // abrir y mantener esas sesiones). k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, k_ESteamNetConnectionEnd_Misc_Max = 5999, };

SteamNetConnectionInfo_t


Describe el estado de una conexión.
struct SteamNetConnectionInfo_t { /// ¿Quién está en el otro extremo? Dependiendo del tipo de conexión y la fase de la conexión, es posible que no sepamos el SteamNetworkingIdentity m_identityRemote; /// Datos de usuario arbitrarios establecidos por el código de aplicación local int64 m_nUserData; /// Handle para escuchar el socket en el que se conectó, o k_HSteamListenSocket_Invalid si iniciamos la conexión HSteamListenSocket m_hListenSocket; /// Dirección remota. Todos podrían ser 0 si no lo sabemos, o si esto es N/A. /// (Por ejemplo, básicamente todo excepto la conexión UDP directa). SteamNetworkingIPAddr m_addrRemote; uint16 m__pad1; /// ¿En qué centro de datos está el host remoto? (0 si no lo sabemos). SteamNetworkingPOPID m_idPOPRemote; /// ¿Qué relé estamos usando para comunicarnos con el host remoto? /// (0 si no es aplicable). SteamNetworkingPOPID m_idPOPRelay; /// Estado del alto nivel de la conexión ESteamNetworkingConnectionState m_eState; /// Causa básica de la terminación de la conexión o problema. /// Ver ESteamNetConnectionEnd para los valores utilizados int m_eEndReason; /// Explicación de la conexión legible por las personas, pero no localizada /// la terminación o el problema. Esto está destinado a la depuración / /// solo con fines de diagnóstico, no para mostrar a los usuarios. Podría /// tener algunos detalles específicos del problema. char m_szEndDebug[]; /// Descripción de la depuración. Esto incluye el identificador de conexión, /// tipo de conexión (e información de pares), y el nombre de la aplicación. /// Esta cadena se usa en varios mensajes de registro interno char m_szConnectionDescription[]; /// Cosas internas, espacio para cambiar la API fácilmente uint32 reservado [64]; };

SteamNetworkingQuickConnectionStatus

Estado de conexión rápida, reducido a algo a lo que se puede llamar con mayor frecuencia sin que sea un golpe de perfección demasiado grande.

struct SteamNetworkingQuickConnectionStatus { /// Estado de alto nivel de la conexión ESteamNetworkingConnectionState m_eState; /// Current ping (ms) int m_nPing; /// Calidad de conexión medida localmente, 0... 1. (Porcentaje de paquetes entregados /// de extremo a extremo en orden). float m_flConnectionQualityLocal; /// Tasa de éxito en la entrega de paquetes observada desde el host remoto float m_flConnectionQualityRemote; /// Tasas de datos actuales del historial reciente. float m_flOutPacketsPerSec; float m_flOutBytesPerSec; float m_flInPacketsPerSec; float m_flInBytesPerSec; /// Estimar la tasa de datos que creemos que podemos enviar a nuestros pares. /// Ten en cuenta que esto podría ser significativamente más alto que m_flOutBytesPerSec, /// significa que la capacidad del canal es mayor que la que está enviando datos. /// (¡Está bien!) int m_nSendRateBytesPerSecond; /// Número de bytes pendientes de envío. Estos son datos que has /// solicitado recientemente para ser enviados, pero aún no se han puesto en el cable. El /// el número confiable TAMBIÉN incluye datos que se colocaron previamente en el cable, /// pero ahora ha sido programado para la retransmisión. Por lo tanto, es posible /// ver m_cbPendingReliable aumentando entre dos verificaciones, incluso si no /// se hicieron llamadas para enviar datos confiables entre las verificaciones. Los datos que están /// a la espera de la demora de Nagle aparecerá en estos números. int m_cbPendingUnreliable; int m_cbPendingReliable; /// Número de bytes de datos confiables que se han colocado en el cable, pero /// para los cuales aún no hemos recibido un acuse de recibo, por lo que podemos /// volver a transmitirlos. int m_cbSentUnackedReliable; /// Si nos pediste que enviásemos un mensaje en este momento, ¿cuánto tiempo duraría ese mensaje /// esperando en la cola antes de que realmente comencemos a poner paquetes en el cable? /// (Y suponiendo que Nagle no causa que ningún paquete se retrase). /// /// En general, los datos que envía la aplicación están limitados por el /// ancho de banda del canal. Si envías datos más rápido que esto, deben /// ponerse en cola y conectarlos a una tasa medida. Incluso enviando una pequeña cantidad /// de los datos (por ejemplo, unos pocos MTU, digamos ~ 3k) requerirá que algunos de los datos se retrasen /// a bit. /// /// En general, el retraso estimado será aproximadamente igual a /// /// ( m_cbPendingUnreliable+m_cbPendingReliable ) / m_nSendRateBytesPerSecond /// /// más o menos un MTU. Depende de cuánto tiempo haya transcurrido desde que el último /// paquete fue puesto en el cable. Por ejemplo, la cola podría haber sido *solo* vaciada, /// y el último paquete colocado en el cable, y estamos exactamente en contra del envío /// del límite de tarifa. En ese caso, podríamos necesitar esperar el tiempo de un paquete para /// pasar antes de que podamos enviar otro de nuevo. En el otro extremo, la cola puede tener datos /// en ella esperando a Nagle. (Esto siempre será menor que un paquete, porque tan pronto /// como tengamos un paquete completo, lo enviaríamos). En ese caso, podríamos estar listos /// para enviar datos ahora, y este valor será 0. SteamNetworkingMicroseconds m_usecQueueTime; };

Mensajes de red


const int k_cbMaxSteamNetworkingSocketsMessageSizeSend = 512 * 1024;
Tamaño máximo de un solo mensaje que podemos ENVIAR.
Nota. Es posible que estemos dispuestos a recibir mensajes grandes, y que nuestros compañeros también lo hagan.

SteamNetworkingMessage_t


Un mensaje que ha sido recibido.
struct SteamNetworkingMessage_t { /// Carga del mensaje void *m_pData; /// Tamaño de la carga. int m_cbSize; /// Para mensajes recibidos en conexiones: ¿de qué conexión proviene? /// Para mensajes salientes: ¿a qué conexión se envía? /// No se utiliza cuando se usa la interfaz ISteamNetworkingMessages HSteamNetConnection m_conn; /// Para mensajes entrantes: ¿quién nos envió esto? /// Para mensajes salientes en la conexión: no se utiliza. /// Para mensajes salientes de la interfaz para ese fin ISteamNetworkingMessages: ¿a quién se lo enviamos? SteamNetworkingIdentity m_identityPeer; /// Para mensajes recibidos en conexiones, esta es la información de usuario /// asociada con la conexión. /// /// Esto «normalmente» es lo mismo que llamar a GetConnection() y después /// recuperar la información del usuario asociada a la conexión, pero con /// las siguientes diferencias sutiles: /// /// - La información del usuario coincidirá con la información de conexión del usuario que se captura /// en ese momento cuando la API devuelve el mensaje. /// Si posteriormente cambias la información de usuario en la conexión, /// esta no se actualizará. /// - Esta es una llamada en línea, así que es mucho más rápida. /// - Es probable que si has cerrado la conexión, no sea posible /// obtener la información de usuario. /// /// No se utiliza al enviar mensajes, int64 m_nConnUserData; /// Marca de tiempo local de cuándo se recibió el mensaje. /// No se utiliza para mensajes salientes. SteamNetworkingMicroseconds m_usecTimeReceived; /// Número del mensaje asignado por el remitente. /// No se utiliza para mensajes salientes int64 m_nMessageNumber; /// Función utilizada para liberar m_pData. Este mecanismo existe para que /// las aplicaciones puedan crear mensajes con búferes asignados desde su propia /// pila y pasarlos a la biblioteca. Esta función será /// normalmente algo como: /// /// free( pMsg->m_pData ); void (*m_pfnFreeData)( SteamNetworkingMessage_t *pMsg ); /// La función se usa para disminuir el cómputo de referencia interna, y si /// es cero se libera el mensaje. No tienes que establecer este puntero de función /// ni necesitas acceder a él directamente. Es mejor que uses la función Release() void (*m_pfnRelease)( SteamNetworkingMessage_t *pMsg ); /// Cuando utilices ISteamNetworkingMessages, el número de canal donde se recibió el mensaje /// (No se utiliza para mensajes enviados o recibidos en «conexiones») int m_nChannel; /// Máscara de bits de marcas k_nSteamNetworkingSend_xxx. /// Para mensajes recibidos, solo la parte de k_nSteamNetworkingSend_Reliable es válida. /// Para mensajes salientes, todas las partes son relevantes int m_nFlags; /// Datos de usuario arbitrarios que se pueden usar al enviar mensajes usando /// ISteamNetworkingUtils::AllocateMessage y ISteamNetworkingSockets::SendMessage. /// (La función callback que establezcas en m_pfnFreeData puede utilizar este campo). /// /// No se utiliza para mensajes recibidos. int64 m_nUserData; /// DEBES hacer esta llamada cuando termines con el objeto, /// para liberar memoria, etc. inline void Release(); };

Marcas utilizadas para enviar mensajes

Estos valores se utilizan en parámetros de máscara de bits para funciones como ISteamNetworkingSockets::SendMessageToConnection

const int k_nSteamNetworkingSend_Unreliable = 0;
Envía el mensaje de forma poco fiable. Se puede perder. Los mensajes *pueden* ser más grandes que una sola MTU (paquete UDP), pero no hay retransmisión, por lo que si se pierde parte del mensaje, se eliminará todo el mensaje.

La API remitente posee cierto conocimiento de la conexión subyacente; por tanto, si no se logra cruzar la red NAT o si hay un ajuste reconocido que afecta a la conexión, el paquete se asignará a un lote hasta que la conexión se vuelva a abrir.

Nota de migración: ¡Esto no es exactamente lo mismo que k_EP2PSendUnreliable! Probáblemente quieras k_ESteamNetworkingSendType_UnreliableNoNagle

const int k_nSteamNetworkingSend_NoNagle = 1;
Deshabilitar Algoritmo de Nagle.

De forma predeterminada, el algoritmo de Nagle se aplica a todos los mensajes salientes. Esto significa que el mensaje NO se enviará de inmediato, en caso de que se envíen más mensajes poco después de enviarlo, que se puedan agrupar. Siempre que haya suficientes datos almacenados en el búfer para llenar un paquete, los paquetes se enviarán de inmediato, pero los paquetes parcialmente completos no se enviarán hasta que el temporizador de Nagle expire. Consulta ISteamNetworkingSockets::FlushMessagesOnConnection, ISteamNetworkingMessages::FlushMessagesToUser

NOTA: No solo envíes todos los mensajes sin Nagle porque deseas que los paquetes "lleguen más rápido". Asegúrate de entender el problema que Nagle está resolviendo antes de desactivarlo. Si estás enviando mensajes pequeños, a menudo muchos al mismo tiempo, entonces es muy probable que sea más eficiente dejar Nagle habilitado. Un uso adecuado típico de este indicador es cuando envía lo que sabe que será el último mensaje enviado durante un tiempo (por ejemplo, el último en la marca de simulación del servidor a un cliente en particular), y utiliza este indicador para vaciar todos los mensajes.

const int k_nSteamNetworkingSend_UnreliableNoNagle = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoNagle;
Envía un mensaje de manera no confiable, omitiendo el algoritmo de Nagle para este mensaje y cualquier mensaje actualmente pendiente en el temporizador de Nagle. Esto es equivalente a usar steamnetworkingtypes::k_ESteamNetworkingSend_Unreliable y luego vaciar inmediatamente los mensajes usando ISteamNetworkingSockets::FlushMessagesOnConnection o ISteamNetworkingMessages::FlushMessagesToUser. (Pero usar este indicador es más eficiente ya que solo hace una llamada a la API).

const int k_nSteamNetworkingSend_NoDelay = 4;
Si el mensaje no se puede enviar muy pronto (debido a que la conexión todavía está realizando algunas negociaciones iniciales, negociaciones de ruta, etc.), simplemente elimínalo. Esto solo es aplicable para mensajes no confiables. El uso de este indicador en mensajes confiables no es válido.


const int k_nSteamNetworkingSend_UnreliableNoDelay = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoDelay|k_nSteamNetworkingSend_NoNagle;
Envía un mensaje no confiable, pero si no se puede enviar de forma relativamente rápida, simplemente suéltalo en lugar de ponerlo en cola. Esto es útil para los mensajes que no son útiles si se retrasan excesivamente, como los datos de voz.

Se dejará un mensaje en las siguientes circunstancias:
  • La conexión no está completamente conectada. (Por ejemplo, los estados "Connecting" o "FindingRoute")
  • Ya hay un número suficientemente grande de mensajes en cola para que el mensaje actual no se coloque en el cable en los próximos ~200 ms o menos.

Si se elimina un mensaje por estos motivos, se devolverá k_EResultIgnored.

NOTA: El algoritmo de Nagle no se usa, y si el mensaje no se descarta, todos los mensajes que esperan en el temporizador de Nagle se vacían inmediatamente.

const int k_nSteamNetworkingSend_Reliable = 8;
Mensaje fiable de envío. Puedes enviar hasta k_cbMaxSteamNetworkingSocketsMessageSizeSend bytes en un solo mensaje. Lleva a cabo la fragmentación o la reconstrucción de mensajes al nivel estructural básico, además de actuar como ventana deslizante para enviar de forma eficiente grandes segmentos de datos.

Se utiliza el algoritmo de Nagle. Consulta las notas en k_ESteamNetworkingSendType_Unreliable para obtener más información. Consulta k_ESteamNetworkingSendType_ReliableNoNagle, ISteamNetworkingSockets::FlushMessagesOnConnection, ISteamNetworkingMessages::FlushMessagesToUser

Nota de migración: NO es lo mismo que k_EP2PSendReliable, es más como k_EP2PSendReliableWithBuffering

const int k_nSteamNetworkingSend_ReliableNoNagle = k_nSteamNetworkingSend_Reliable|k_nSteamNetworkingSend_NoNagle;
Envía un mensaje de manera confiable, pero evita el algoritmo de Nagle.

Nota de migración: esto es equivalente a k_EP2PSendReliable

Ubicación y medición de Ping

ISteamNetworkingutils tiene funciones para estimar el tiempo de ping entre dos hosts de Internet sin enviar paquetes.

SteamNetworkingPingLocation_t


struct SteamNetworkPingLocation_t { uint8 m_data[]; }
Objeto opaco que describe una "ubicación" en internet, con detalles suficientes para que podamos estimar razonablemente un límite superior en el ping entre los dos hosts, incluso si no es posible una ruta directa entre los hosts, y la conexión debe enrutarse a través de la red del relé de datagrama de Steam.

Esto no contiene ninguna información que identifique al host. De hecho, si dos hosts están en el mismo edificio o tienen características de red casi idénticas, entonces es válido usar el mismo objeto de ubicación para ambos.

NOTA: ¡Este objeto solo debe usarse en el mismo proceso! ¡No lo serialices, no lo envíes por cable o lo conserves en un archivo o base de datos! Si necesitas hacerlo, conviértelo a una representación de cadena usando los métodos en ISteamNetworkingUtils.

k_cchMaxSteamNetworkingPingLocationString


const int k_cchMaxSteamNetworkingPingLocationString = 1024;
Longitud máxima posible de una ubicación de ping, en formato de cadena. Este es un valor de peor caso extremadamente conservador que deja espacio para futuras mejoras de sintaxis. La mayoría de las cadenas en la práctica son mucho más cortas. Si almacenas muchos de estos, es muy probable que te beneficies del uso de la memoria dinámica.

Configuración

Puedes controlar diferentes parámetros operativos, de forma global o específica de conexión. Los métodos para hacer esto están en ISteamNetworkingUtils

ESteamNetworkingConfigScope


Los valores de configuración se pueden aplicar a diferentes tipos de objetos.
enum ESteamNetworkingConfigScope { /// Obtener / establecer la opción global, o por defecto. Incluso opciones que se aplican a ámbitos más específicos /// tienen un alcance global, y es posible que solo puedas cambiar los valores predeterminados globales. Si /// necesitas diferentes configuraciones por conexión (por ejemplo), entonces deberás configurar esas /// opciones en el ámbito más específico. k_ESteamNetworkingConfig_Global = 1, /// Algunas opciones son específicas de una interfaz particular. Ten en cuenta que todas las conexiones /// y los ajustes de socket de escucha también se pueden establecer en el nivel de la interfaz, y se /// aplica a los objetos creados a través de esas interfaces. k_ESteamNetworkingConfig_SocketsInterface = 2, /// Opciones para un socket de escucha. Las opciones de socket de escucha se pueden configurar en la capa de la interfaz, /// si tiene múltiples sockets de escucha y todos usan las mismas opciones. /// También puede configurar las opciones de conexión en un socket de escucha, y estos establecen los valores predeterminados /// para todas las conexiones aceptadas a través de este socket de escucha. (Se utilizarán si no /// estableces una opción de conexión.) k_ESteamNetworkingConfig_ListenSocket = 3, /// Opciones para una conexión específica. k_ESteamNetworkingConfig_Connection = 4, };

ESteamNetworkingConfigDataType


Diferentes valores de configuración tienen diferentes tipos de datos.
enum ESteamNetworkingConfigDataType { k_ESteamNetworkingConfig_Int32 = 1, k_ESteamNetworkingConfig_Int64 = 2, k_ESteamNetworkingConfig_Float = 3, k_ESteamNetworkingConfig_String = 4, k_ESteamNetworkingConfig_FunctionPtr = 5, // NOTA: Al configurar las funciones callback, debe colocar el puntero en una variable y pasar un puntero a esa variable. };

ESteamNetworkingConfigValue


Opciones de configuración
enumeración ESteamNetworkingConfigValue { k_ESteamNetworkingConfig_Invalid = 0, /// [global float, 0--100] Descarta aleatoriamente el N pct de paquetes en lugar de enviar / recibir /// Esta es solo una opción global, ya que se aplica a un nivel bajo /// donde no tenemos mucho contexto k_ESteamNetworkingConfig_FakePacketLoss_Send = 2, k_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, /// [global int32]. Retrasar todos los paquetes salientes / entrantes por N ms k_ESteamNetworkingConfig_FakePacketLag_Send = 4, k_ESteamNetworkingConfig_FakePacketLag_Recv = 5, /// [global float] 0-100 porcentaje de paquetes que agregaremos retardo adicional /// a (haciendo que se reordenen) k_ESteamNetworkingConfig_FakePacketReorder_Send = 6, k_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, /// [global int32] Retardo adicional, en ms, para aplicar a paquetes reordenados. k_ESteamNetworkingConfig_FakePacketReorder_Time = 8, /// [global float 0--100] Duplicamos globalmente algún porcentaje de paquetes que enviamos k_ESteamNetworkingConfig_FakePacketDup_Send = 26, k_ESteamNetworkingConfig_FakePacketDup_Recv = 27, /// [global int32] Cantidad de retraso, en ms, para retrasar paquetes duplicados. /// (Elegimos un retraso aleatorio entre 0 y este valor) k_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, /// [connection int32] Timeout value (in ms) to use when first connecting k_ESteamNetworkingConfig_TimeoutInitial = 24, /// [connection int32] Valor de tiempo de espera (en ms) para usar cuando se conecta por primera vez k_ESteamNetworkingConfig_TimeoutConnected = 25, /// [connection int32] Límite superior de bytes pendientes en búfer para enviar, /// si se alcanza esto, SendMessage devolverá k_EResultLimitExceeded /// El valor predeterminado es 512k (524288 bytes) k_ESteamNetworkingConfig_SendBufferSize = 9, /// [connection int32] Amplitud de velocidad de envío mínima / máxima, 0 no es límite. /// Este valor controlará la velocidad de envío mínima / máxima permitida que /// se permite alcanzar la estimación de ancho de banda. El valor predeterminado es 0 (sin límite) k_ESteamNetworkingConfig_SendRateMin = 10, k_ESteamNetworkingConfig_SendRateMax = 11, /// [connection int32] tiempo de Nagle, en microsegundos. Cuando se llama a SendMessage, si /// el mensaje saliente es menor que el tamaño de la MTU, será /// en cola para un retraso igual al valor del temporizador de Nagle. Esto es para asegurar /// que si la aplicación envía varios mensajes pequeños rápidamente, son /// agrupados en un solo paquete. /// Ver el histórico RFC 896. El valor está en microsegundos. /// El valor predeterminado es 5000us (5ms). k_ESteamNetworkingConfig_NagleTime = 12, /// [connection int32] No fallan automáticamente las conexiones IP que no tienen /// autenticación fuerte. En los clientes, esto significa que intentaremos la conexión incluso si /// no conocemos nuestra identidad o no podemos obtener un certificado. En el servidor, significa que /// no rechazaremos automáticamente una conexión debido a un error de autenticación. /// (Puedes examinar la conexión entrante y decidir si aceptarla). k_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, // // Configuraciones para conexiones retransmitidas SDR // /// [int32 global] Si todos los primeros N pings a un puerto fallan, marca ese puerto como no disponible durante /// un rato, y prueba otro diferente. Algunos ISP y routers pueden quitar el primer /// paquete, por lo que establecerlo como el número 1 puede afectar enormemente a las comunicaciones. k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, /// [int32 global] Si fallan N pings consecutivos a un puerto, después de haber recibido exitosamente /// la comunicación, marca ese puerto como no disponible por un tiempo e intenta con /// otro distinto. k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, /// [int32 global] Número mínimo de pings de por vida que debemos enviar, antes de pensar que nuestra estimación /// es sólida. El primer ping a cada clúster se retrasa con frecuencia debido a NAT, /// routers que no tienen la mejor ruta, etc. Hasta que hayamos enviado un número suficiente /// de pings, nuestra estimación es a menudo inexacta. Sigue haciendo ping hasta que obtengamos esto /// many pings. k_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, /// [int32 global] Establece que todo el tráfico de datagramas de Steam se origine en el mismo /// puerto local. De forma predeterminada, abrimos un nuevo socket UDP (en un puerto local diferente) /// para cada relé. Esto es ligeramente peor, pero funciona con /// algunos routers que no implementan NAT correctamente. Si tienes internamente /// problemas para hablar con los relés que pueden estar relacionados con NAT, intenta alternar /// esta etiqueta k_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, /// [cadena global] Código del clúster de retransmisión para forzar su uso. Si no está vacío, /// solo usaremos relés en ese cluster. P.ej. 'iad' k_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, /// [cadena de conexión] Para la depuración, genera nuestro propio ticket (sin firmar), utilizando /// la dirección especificada del servidor de juegos. El router debe estar configurado para aceptar /// tickets sin firma. k_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, /// [cadena global] para depuración. Reemplaza la lista de relés de la configuración con /// este conjunto (tal vez solo uno). Lista separada por comas. k_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, // // Niveles de registro para la información de depuración. Una prioridad más alta // (menor valor numérico) hará que se impriman más cosas. // k_ESteamNetworkingConfig_LogLevel_AckRTT = 13, // [connection int32] Cálculos de RTT para pings en línea y respuestas k_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, // [connection int32] registra los paquetes de SNP enviados k_ESteamNetworkingConfig_LogLevel_Message = 15, // [connection int32] egistra cada mensaje enviado / recibido k_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, // [connection int32] paquetes descartados k_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, // [connection int32] Mensajes de encuentro P2P k_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, // [global int32] relés de ping };

ESteamNetworkingGetConfigValueResult


Valor de retorno de ISteamNetworkintgUtils::GetConfigValue
enumeración ESteamNetworkingGetConfigValueResult { k_ESteamNetworkingGetConfigValue_BadValue = -1, // No hay tal valor de configuración k_ESteamNetworkingGetConfigValue_BadScopeObj = -2, // Controlador de conexión incorrecto, etc k_ESteamNetworkingGetConfigValue_BufferTooSmall = -3, // No se pudo ajustar el resultado en su búfer k_ESteamNetworkingGetConfigValue_OK = 1, k_ESteamNetworkingGetConfigValue_OKInherited = 2, // No se estableció un valor en este nivel, pero se devolvió el valor efectivo (heredado). k_ESteamNetworkingGetConfigValueResult__Force32Bit = 0x7fffffff };

SteamNetworkingConfigValue_t


En unos pocos lugares necesitamos establecer opciones de configuración en sockets y conexiones de escucha, y hacer que tengan efecto antes de que el socket o la conexión de escucha empiece de verdad a hacer algo. Crear el objeto y luego establecer las opciones "inmediatamente" después de su creación no funciona bien, pues se pueden recibir paquetes de red entre el momento de creación del objeto y el de la aplicación de las opciones. Para establecer opciones en el momento de la creación de manera confiable, deben pasarse a la función de creación. Esta estructura se usa para pasar esas opciones.

Para ver el significado de estos campos, consulta ISteamNetworkingUtils::SetConfigValue. Básicamente, cuando se crea el objeto, simplemente iteramos sobre la lista de opciones y llamamos a ISteamNetworkingUtils::SetConfigValueStruct, donde el objeto que se está creando proporciona los argumentos de ámbito.
struct SteamNetworkingConfigValue_t { /// ¿Qué opción se está estableciendo? ESteamNetworkingConfigValue m_eValue; /// ¿Qué campo rellenaste abajo? ESteamNetworkingConfigDataType m_eDataType; /// Valor de la opción union { int32_t m_int32; int64_t m_int64; float m_float; const char *m_string; // Puntos para tu búfer '\0'-terminated void *m_functionPtr; } m_val; };

Centros de datos de Valve

Se utiliza para describir la topología de la red de Valve, identificar centros de datos, etc.

typedef uint32 SteamNetworkingPOPID;
Identificador utilizado para un punto de presencia de ubicación de red. (Por ejemplo, un centro de datos de Valve).
Normalmente no necesitarás manipularlos directamente.

SteamNetworkingPOPID CalculateSteamNetworkingPOPIDFromString( const char *pszCode )
Convierte la id. de 3 o 4 caracteres a int de 32 bits.

plantilla <int N> inline void GetSteamNetworkingLocationPOPStringFromID( SteamNetworkingPOPID id, char (&szCode)[N] )
Desempaqueta la representación de enteros a cadenas, incluida la terminación '\0'. Tu cadena debe tener al menos 5 bytes de tamaño. (No se podrá compilar si este no es el caso).