Documentación de Steamworks
Interfaz ISteamNetworkingSockets
API de red similar a los socket Berkeley, pero para juegos.

  • Es una API orientada a la conexión (como TCP, no UDP). Al enviar y recibir mensajes, el nodo par se identifica mediante un identificador de conexión.
  • Pero a diferencia de TCP, este tipo de conexión está orientado a mensajes, no a retransmisiones. (Los límites entre los mensajes son mantenidos por la API).
  • Se admiten mensajes confiables y no confiables.
  • Los mensajes grandes se dividen en varios paquetes, los mensajes pequeños se combinan en menos paquetes.
  • Una robusta estrategia ACK / reensamblado / retransmisión.
  • Fuerte encriptación y autenticación. Cuando un jugador se conecta, puede estar seguro de que si se autentica cierto SteamID, alguien que tiene acceso a la cuenta de esa persona ha autorizado la conexión. La escucha/manipulación requiere piratería en el proceso protegido por VAC. La personificación requiere acceso al ordenador del objetivo.
  • Admite conexiones retransmitidas a través de la red de Valve. Esto evita que se revelen las direcciones IP, protegiendo a tus jugadores y servidores de juegos de ataques.
  • También es compatible con la conectividad estándar sobre UDP simple utilizando IPv4 o IPv6.

Documentos relacionados:
  • Conectividad de red de Steam descripción general de las diferentes API de networking.
  • ISteamNetworkingUtils Utilidades para medir el ping y estimar el tiempo de ping entre pares.
  • steamnetworkingtypes Varios tipos y utilidades.
  • Steam Datagram Relay Un servicio para transmitir el tráfico de tu juego a través de la red troncal de Valve. Esto evita que se revelen las direcciones IP y, en muchos casos, mejora los tiempos de ping y la calidad de la conexión.
  • ISteamNetworkingMessages es una interfaz de estilo UDP. Envía y recibe mensajes especificando el par destinatario en cada llamada de envío, en lugar de establecer primero una conexión. Aún se usan las mismas conexiones internamente, así que todavía puedes obtener el mismo rendimiento, pero las conexiones se crean y las inactivas se detienen automáticamente para ti, y no recibes tanto control sobre la conexión ni información sobre su estado.

Una versión de código abierto de esta API está disponible en GitHub. Puedes usarlo para cualquier propósito que quieras. Para utilizar la red Valve, debes ser un asociado de Steam y usar la versión en el SDK de Steamworks.

Las funciones miembro para ISteamNetworkingSockets se llaman a través de la función de acceso global SteamNetworkingSockets().

Gestión de conexiones

CreateListenSocketIP

HSteamListenSocket CreateListenSocketIP( const SteamNetworkingIPAddr &localAddress, int nOptions, const SteamNetworkingConfigValue_t *pOptions );

Crea un socket de «servidor» que detecta clientes a los que conectarse mediante una llamada a ConnectByIPAddress, a través de UDP ordinario (IPv4 o IPv6).

Debes seleccionar un puerto local específico como puerto de escucha y configurarlo como el campo de puerto de la dirección local.

Por lo general, establecerás la parte de la IP de la dirección con un valor de cero, (SteamNetworkingIPAddr::Clear()). Esto significa que no se enlazará a ninguna interfaz local en particular (es decir, igual que con INADDR_ANY en código de socket simple). Además, si es posible, el socket se enlazará en el modo de doble pila, lo que significa que puede aceptar conexiones de clientes IPv4 e IPv6. Si de verdad deseas enlazar una interfaz en particular, establece la dirección IPv4 o IPv6 apropiada como dirección local.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

Cuando un cliente intente conectarse, se publicará una SteamNetConnectionStatusChangedCallback_t. La conexión estará en el estado k_ESteamNetworkingConnectionState_Connecting.

ConnectByIPAddress

HSteamNetConnection ConnectByIPAddress( const SteamNetworkingIPAddr &address, int nOptions, const SteamNetworkingConfigValue_t *pOptions );

Crea una conexión y comienza a hablar con un servidor mediante UDP en la dirección IPv4 o IPv6 correspondiente. El host remoto debe estar escuchando con una llamada correspondiente a ISteamnetworkingSockets::CreateListenSocketIP en el puerto especificado.

Cuando iniciemos la conexión, se activará una función callback SteamNetConnectionStatusChangedCallback_t, y luego otra cuando se agote el tiempo de espera o una conexión se realice correctamente.

Si el servidor no tiene ninguna identidad configurada, entonces su dirección de red será la única identidad en uso. De otro modo, el host de la red puede proporcionar una identidad específica de la plataforma con o sin un certificado válido para autenticar esa identidad. Estos detalles se incluirán en SteamNetConnectionStatusChangedCallback_t. Depende de tu aplicación decidir si se permite la conexión.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

CreateListenSocketP2P

HSteamListenSocket CreateListenSocketP2P( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions );

Como CreateListenSocketIP, pero los clientes se conectarán usando ConnectP2P. La conexión se retransmitirá a través de la red de Valve.

nLocalVirtualPort especifica cómo pueden conectarse los clientes a este socket utilizando ConnectP2P. Es muy común que las aplicaciones solo tengan un socket de escucha. En ese caso, usa cero. Si necesitas abrir varios sockets de escucha y los clientes pueden conectarse a uno u otro, entonces nLocalVirtualPort debe ser un número entero pequeño (< 1000) único para cada socket de escucha que crees.

Si estás escuchando en un servidor dedicado en un centro de datos conocido, puedes escuchar usando esta función en lugar de CreateHostedDedicatedServerListenSocket para que los clientes pueda conectarse sin un ticket. Cualquier usuario que tenga la aplicación y haya iniciado sesión en Steam podrá intentar conectarse a tu servidor. Además, puede que los usuarios tengan que estar conectados a Steam para realizar un intento de conexión, siendo esta otra parte del proceso que podría fallar. Una vez que se obtiene un ticket, los usuarios podrán conectarse a tu servidor incluso si se desconectaron de Steam o si Steam está desconectado.

Si optas por esta opción, te recomendamos que llames a ISteamNetworkingUtils::InitRelayNetworkAccess cuando tu aplicación se inicie.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

ConnectP2P

HSteamNetConnection ConnectP2P( const SteamNetworkingIdentity &identityRemote, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions );
Comienza conectándose a un par identificado mediante un identificador específico de la plataforma. Esto utiliza el servicio de encuentro predeterminado, que depende de la configuración de la plataforma y la biblioteca. Por ejemplo, en Steam, pasa por el backend de Steam. El tráfico se retransmite a través de la red Steam Datagram Relay.

Si optas por esta opción, te recomendamos que llames a ISteamNetworkingUtils::InitRelayNetworkAccess cuando tu aplicación se inicie.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

AcceptConnection

EResult AcceptConnection( HSteamNetConnection hConn );

Acepta una conexión entrante que se haya recibido en un socket de escucha.

Cuando se recibe un intento de conexión (quizás después de que se hayan intercambiado algunos paquetes básicos de enlace para evitar una suplantación común), se crea un objeto de interfaz de conexión en el estado k_ESteamNetworkingConnectionState_Connecting y se publica un SteamNetConnectionStatusChangedCallback_t. En este momento, tu aplicación DEBE aceptar o cerrar la conexión. Puede que no lo ignore. Al aceptar la conexión, se cambiará al estado conectado o al estado de la ruta de búsqueda, dependiendo del tipo de conexión.

No tardes más de uno o dos segundos, porque aceptar la conexión es lo que realmente envía la respuesta, notificando a los clientes que están conectados. Si tardas en hacerlo, desde la perspectiva de los clientes daría la impresión de que la red no responde y los clientes podrían suspender el intento de conexión. En otras palabras, los clientes no pueden distinguir entre un retraso causado por problemas de red y un retraso causado por la aplicación.

Esto significa que, si tu aplicación no procesa en unos pocos segundos las funciones callback (por ejemplo, al cargar un mapa), existe la posibilidad de que los clientes intenten conectarse en ese intervalo y se produzca un error en la conexión debido al tiempo de espera.

Si la aplicación no responde al intento de conexión de manera oportuna y dejamos de recibir comunicaciones de los clientes, el intento de conexión
resultará en un tiempo de espera agotado localmente, y la conexión pasará al estado k_ESteamNetworkingConnectionState_ProblemDetectedLocally. Los clientes también puede cerrar la conexión antes de que se acepte, y también es posible una transición a k_ESteamNetworkingConnectionState_ClosedByPeer dependiendo de la secuencia exacta de eventos.

Devuelve:
  • k_EResultInvalidParam si el identificador no es válido.
  • k_EResultInvalidState si la conexión no está en el estado apropiado. (Recuerda que el estado de la conexión puede cambiar entre el momento en que la notificación se publica en la cola y cuando la aplicación la recibe).

Nota sobre las opciones de configuración de las conexiones: Si necesitas establecer alguna opción de configuración que sea común a todas las conexiones aceptadas a través de un socket de escucha en particular, considera configurar las opciones en el socket de escucha, ya que dichas opciones se heredan automáticamente. Si realmente necesitas establecer opciones específicas para una conexión, es seguro establecerlas en la propia conexión antes de aceptarla.

CloseConnection

bool CloseConnection( HSteamNetConnection hPeer, int nReason, const char *pszDebug, bool bEnableLinger );

Se desconecta del host remoto e invalida el handle de conexión. Cualquier dato no leído en la conexión se descarta.

nReason es un código definido por la aplicación que se recibirá en el otro extremo y se registrará (cuando sea posible) en el análisis de backend. El valor debe provenir de un rango restringido. Consulta ESteamNetConnectionEnd. Si no necesitas comunicar ninguna información al host remoto y no deseas que los análisis puedan distinguir las terminaciones de conexión normales de las excepcionales, puedes pasar un valor de cero, en cuyo caso se utilizará el valor genérico de k_ESteamNetConnectionEnd_App_Generic.

pszDebug es una cadena de diagnóstico opcional que las personas pueden leer y que será recibida por el host remoto y registrada (cuando sea posible) en el análisis de backend.

Opcionalmente, puedes colocar el socket en un estado de «persistencia», que hace que la conexión intente entregar los mensajes fiables salientes restantes antes de cerrar la conexión. De lo contrario, se descartan los datos fiables no enviados. En cualquier caso, una vez que cierres la conexión, no tendrás más visibilidad del estado de la conexión o de los mensajes. En algunos casos de uso, esto es aceptable. Si no lo es, debes esperar para cerrar la conexión. Recuerda que este es un protocolo de aplicación, no un protocolo de kernel como el de TCP. Por lo tanto, debes asegurarte de que la aplicación se ejecute durante el tiempo suficiente para que los datos se borren.

Si la conexión ya ha finalizado (k_ESteamNetworkingConnectionState_ClosedByPeer o k_ESteamNetworkingConnectionState_ProblemDetectedLocally) y simplemente estás liberando el objeto de conexión, se ignoran nReason, pszDebug y bEnableLinger.

CloseListenSocket

bool CloseListenSocket( HSteamListenSocket hSocket );

Destruye un socket de escucha. Todas las conexiones que se aceptaron en el socket de escucha se cierran inesperadamente.

CreateSocketPair

bool CreateSocketPair( HSteamNetConnection *pOutConnection1, HSteamNetConnection *pOutConnection2, bool bUseNetworkLoopback, const SteamNetworkingIdentity *pIdentity1, const SteamNetworkingIdentity *pIdentity2 );

Crea un par de conexiones que hablan entre sí, por ejemplo, una conexión de bucle invertido. Esto es muy útil para realizar pruebas, o para que el código de tu cliente o servidor funcionen igual, incluso cuando ejecutes un servidor local.

Las dos conexiones se colocarán inmediatamente en el estado conectado y no se publicarán funciones callback inmediatamente. Después de esto, si cierras cualquiera de las conexiones, la otra recibirá una función callback, exactamente como si se estuvieran comunicando a través de la red. ¡Debes cerrar *ambos* lados para limpiar completamente los recursos!

De forma predeterminada, se utilizan búferes internos, evitando por completo la red, el desglose de mensajes en paquetes, el cifrado, la copia de la carga útil, etc. Esto significa que los paquetes de bucle invertido, por defecto, no simularán ningún retraso o pérdida. Pasar el valor true para bUseNetworkLoopback hará que el par de sockets envíe paquetes a través del dispositivo de bucle invertido de red local (127.0.0.1) en puertos efímeros. En este caso se admiten falsos retrasos y pérdidas, y el tiempo de la CPU se emplea para cifrar y descifrar.

Si deseas asignar una identidad específica a cualquiera de las conexiones, puedes pasar una identidad particular. De lo contrario, si pasas nullptr, la conexión respectiva asumirá una identidad genérica de host local. Si utilizas un bucle invertido de red real, esto podría traducirse al propio puerto enlazado de bucle invertido. De lo contrario, el puerto será cero.

Enviando y recibiendo mensajes

SendMessageToConnection

EResult SendMessageToConnection( HSteamNetConnection hConn, const void *pData, uint32 cbData, int nSendFlags, int64 *pOutMessageNumber );
Envía un mensaje al host remoto en la conexión especificada.

nSendFlags determina cuándo deben almacenarse los datos en el búfer, las garantías de entrega que se proporcionarán, etc. Ejemplo:
  • k_nSteamNetworkingSend_Unreliable
  • k_nSteamNetworkingSend_Reliable
  • k_nSteamNetworkingSend_NoNagle
  • k_nSteamNetworkingSend_NoDelay

Ten en cuenta que la semántica que utilizamos para los mensajes no es exactamente la misma que la de un socket estándar de «secuencia». (SOCK_STREAM) En los sockets de secuencias ordinarios, los límites entre los fragmentos no se consideran relevantes, y los tamaños de los fragmentos de datos escritos no coincidirán necesariamente con los tamaños de los fragmentos que las lecturas devuelven en el otro extremo. Puede que el host remoto lea un fragmento parcial o que los fragmentos se fusionen. Sin embargo, para la semántica del mensaje que se usa aquí, los tamaños SÍ coincidirán. Una por una, cada llamada de envío se corresponderá con una llamada de lectura realizada correctamente en el host remoto. Si estás transfiriendo el código existente de secuencias existente a la semántica de los mensajes fiables, tu código debería funcionar igual, ya que la semántica fiable de los mensajes es más estricta que la semántica de secuencias. La única advertencia está relacionada con el rendimiento: hay una sobrecarga por mensaje para retener el tamaño de los mensajes, por lo que si su código envía muchos fragmentos pequeños de datos, el rendimiento se verá afectado. Los códigos basados en sockets de secuencias que no escriban fragmentos excesivamente pequeños funcionarán sin ningún cambio.

pOutMessageNumber es un puntero opcional para recibir el número de mensaje asignado al mensaje, si el envío se realizó correctamente.

Devuelve:
  • k_EResultInvalidParam: identificador de conexión no válido, o el mensaje individual es demasiado grande. (Consulta: k_cbMaxSteamNetworkingSocketsMessageSizeSend)
  • k_EResultInvalidState: la conexión está en un estado no válido.
  • k_EResultNoConnection: la conexión ha finalizado.
  • k_EResultIgnored: Utilizaste k_nSteamNetworkingSend_NoDelay y el mensaje se eliminó porque no estábamos listos para enviarlo.
  • k_EResultLimitExceeded: ya había demasiados datos en cola para ser enviados. (See k_ESteamNetworkingConfig_SendBufferSize)

SendMessages

void SendMessages( int nMessages, SteamNetworkingMessage_t *const *pMessages, int64 *pOutMessageNumberOrResult );
Envía uno o más mensajes sin copiar la carga útil del mensaje. Esta es la forma más eficiente de enviar mensajes. Para usar esta función, primero debes asignar un objeto de mensaje usando ISteamNetworkingUtils::AllocateMessage. No declares uno en la pila ni asignes el tuyo.

Debes completar la carga útil del mensaje. Puedes dejar que asigne el búfer por ti y luego completar la carga útil, o si ya tienes un búfer asignado, simplemente puedes apuntar m_pData a tu búfer y establecer la función callback para que sea la función adecuada para liberarlo. Ten en cuenta que si usas tu propio búfer, DEBE permanecer válido hasta que se ejecute la función callback. Además, ten en cuenta que tu función callback se puede invocar en cualquier momento desde cualquier subproceso (tal vez incluso antes de que SendMessages devuelva resultados), por lo que DEBE ejecutarse rápidamente y tener seguridad en hilos.

También DEBES completar:
  • m_conn: El identificador de la conexión para enviar el mensaje a
  • m_nFlags: Máscara de bits de las banderas k_nSteamNetworkingSend_xxx.

Todos los demás campos están actualmente reservados y no deben modificarse.

La biblioteca se hará cargo de las estructuras de los mensajes. Pueden modificarse o dejar de ser válidos en cualquier momento, por lo que no debes leer los mensajes después de pasarlos a esta función.

pOutMessageNumberOrResult es una matriz opcional que recibirá, para cada mensaje, el número de mensaje que se asignó al mensaje si el envío se realizó correctamente. Si el envío falla, se coloca un valor negativo de EResult en la matriz. Por ejemplo, la matriz contendrá -k_EResultInvalidState si la conexión estaba en un estado no válido. Consulta SendMessageToConnection para ver los posibles códigos de fallo.

FlushMessagesOnConnection

EResult FlushMessagesOnConnection( HSteamNetConnection hConn );
Vacía los mensajes que estén esperando al temporizador de Nagle y los envía durante la próxima oportunidad de transmisión (a menudo eso significa ahora).

Si Nagle está habilitado (está activado de manera predeterminada), al llamar a SendMessageToConnection, el mensaje se almacenará en el búfer hasta que se envíe para combinar pequeños mensajes en el mismo paquete. Consulta k_ESteamNetworkingConfig_NagleTime.

Devuelve:
  • k_EResultInvalidParam: invalid connection handle
  • k_EResultInvalidState: la conexión está en un estado no válido.
  • k_EResultNoConnection: la conexión ha finalizado.
  • k_EResultIgnored: no estábamos (aún) conectados, por lo que esta operación no tiene efecto.

ReceiveMessagesOnConnection

int ReceiveMessagesOnConnection( HSteamNetConnection hConn, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages );
Obtiene los siguientes mensajes disponibles de la conexión, si los hay. Devuelve el número de mensajes devueltos en tu matriz, hasta un máximo de nMaxMessages.
Si el handle de conexión no es válido, devuelve -1. Si no hay datos disponibles, devuelve 0.

El orden de los mensajes devueltos en la matriz es relevante. Los mensajes fiables se recibirán en el orden en que se enviaron y con los mismos tamaños. Consulta SendMessageToConnection para más información sobre esta diferencia sutil de un socket de secuencia.

Los mensajes que no sean fiables pueden ser descartados o entregados fuera de orden entre sí o con respecto a mensajes fiables.

Si se devuelve algún mensaje, DEBES llamar a SteamNetworkingMessage_t::Release() para que cada uno de ellos libere recursos una vez que haya terminado. Es seguro mantener el objeto activo durante un tiempo (ponerlo en una cola, etc.), y puedes llamar a Release() desde cualquier subproceso.

Sondeo eficiente de múltiples conexiones


Un grupo de sondeo es un conjunto de conexiones que pueden sondearse de manera eficiente. En esta API, sondear una conexión significa obtener todos los mensajes pendientes. En realidad, no tenemos una API para sondear el estado de la conexión, como los sockets BSD.

CreatePollGroup

HSteamNetPollGroup CreatePollGroup()
Crea un nuevo grupo de sondeo.

Debes eliminar el grupo de sondeo cuando hayas terminado de usarlo DestroyPollGroup.

DestroyPollGroup

bool DestroyPollGroup( HSteamNetPollGroup hPollGroup )
Elimina un grupo de sondeo creado con CreatePollGroup.

Si hay conexiones en el grupo de sondeo, se eliminan del grupo y se dejan en un estado en el que no forman parte de ningún grupo de sondeo. Devuelve false si se pasa un handle de grupo de sondeo no válido.

SetConnectionPollGroup

bool SetConnectionPollGroup( HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup );

Asigna una conexión a un grupo de sondeo. Ten en cuenta que una conexión solo puede pertenecer a un único grupo de sondeo. Añadir una conexión a un grupo de sondeo la eliminará implícitamente de cualquier otro grupo de sondeo en el que se encuentre.

Puedes pasar k_HSteamNetPollGroup_Invalid para eliminar una conexión de su grupo de sondeo actual sin añadirla a un nuevo grupo de sondeo.

Si hay mensajes recibidos actualmente pendientes en la conexión, se intentará añadirlos a la cola de mensajes para el grupo de sondeo en el orden aproximado que se hubiera aplicado si la conexión ya fuera parte del grupo de sondeo en el momento en que se recibieron los mensajes.

Devuelve false si el handle de conexión no es válido, si el handle del grupo de sondeo no es válido o si no es k_HSteamNetPollGroup_Invalid.

ReceiveMessagesOnPollGroup

int ReceiveMessagesOnPollGroup( HSteamNetPollGroup hPollGroup, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages );

Igual que ReceiveMessagesOnConnection, pero devolverá los siguientes mensajes disponibles en cualquier conexión en el grupo de sondeo. Examina SteamNetworkingMessage_t::m_conn para saber qué conexión. SteamNetworkingMessage_t::m_nConnUserData también puede ser útil.

El orden de entrega de mensajes entre diferentes conexiones generalmente coincidirá con el orden en que se recibió el último paquete que completó el mensaje. Pero esto no es una garantía sólida, especialmente para los paquetes que se reciben justo en el momento en el que se está asignando una conexión al grupo de sondeo.

El orden de entrega de los mensajes en la misma conexión está bien definido y las mismas garantías están presentes como se menciona en ReceiveMessagesOnConnection. Pero los mensajes no están agrupados por conexión, por lo que no necesariamente aparecerán consecutivamente en la lista; pueden estar entrelazados con mensajes para otras conexiones.

Información de la conexión

GetConnectionInfo

bool GetConnectionInfo( HSteamNetConnection hConn, SteamNetConnectionInfo_t *pInfo );
Devuelve información básica sobre el estado de alto nivel de la conexión.
Devuelve false si el handle de conexión no es válido.

GetConnectionRealTimeStatus

EResult GetConnectionRealTimeStatus( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus, int nLanes, SteamNetConnectionRealTimeLaneStatus_t *pLanes );

Devuelve un conjunto pequeño de información sobre el estado en tiempo real de la conexión y el estado de la cola de cada línea.

Puede que pStatus sea NULL si no se desea la información. Por ejemplo, si solo te interesa la información de las líneas.

Cuando se introduce, nLanes especifica la longitud de la matriz de pLanes. Este valor puede ser 0 si no quieres recibir ninguna información de las líneas. No pasa nada si este valor es menor que el número total de líneas configuradas.

pLanes apunta a una matriz que recibirá información específica de las líneas. Puede ser NULL si no se necesita.

Valores devueltos:
  • k_EResultNoConnection: el handle de conexión no es válido o la conexión se ha cerrado.
  • k_EResultInvalidParam: nLanes es incorrecto.

GetDetailedConnectionStatus

int GetDetailedConnectionStatus( HSteamNetConnection hConn, char *pszBuf, int cbBuf );
Devuelve estadísticas de conexión muy detalladas en formato de texto de diagnóstico. Útil para volcar a un registro, etc. El formato de esta información está sujeto a cambios.

Devuelve:
  • -1: error (handle de conexión incorrecto).
  • 0: tu búfer se llenó y finalizó con un carácter nulo ('\0').
  • >0: tu búfer resultó en nullptr o era demasiado pequeño y el texto se truncó. Vuelve a intentarlo con un búfer de al menos N bytes.

SetConnectionUserData

bool SetConnectionUserData( HSteamNetConnection hPeer, int64 nUserData );

Establece los datos de usuario para las conexiones. Los datos se utilizan en los siguientes lugares:

¿Necesitas configurar esto de forma atómica cuando se cree la conexión? Consulta k_ESteamNetworkingConfig_ConnectionUserData.

AVISO: Ten *mucho cuidado* cuando uses el valor proporcionado por las estructuras de las funciones callback. Las funciones callback se ponen en cola y los valores que recibirás en tu función callback son los datos de usuario que estaban en vigor cuando esa función se puso en cola. ¡Hay condiciones de carrera sutiles que pueden ocurrir si no
entiendes esto!

Si algún mensaje entrante para esta conexión se pone en cola, el campo de datos de usuario se actualizará, de manera que si recibes mensajes (por ejemplo, con ReceiveMessagesOnConnection) siempre tendrán los datos de usuario más recientes. Por lo tanto, las condiciones de carrera complicadas que pueden ocurrir con las funciones callback no se aplican a la recuperación de mensajes.

Devuelve false si el handle no es válido.

GetConnectionUserData

int64 GetConnectionUserData( HSteamNetConnection hPeer );
Obtiene los datos de conexión del usuario. Devuelve -1 si el handle no es válido o si no has configurado ningún dato de usuario en la conexión.

SetConnectionName

void SetConnectionName( HSteamNetConnection hPeer, const char *pszName );
Establece un nombre para la conexión y se utiliza principalmente para la depuración.

GetConnectionName

bool GetConnectionName( HSteamNetConnection hPeer, char *pszName, int nMaxLen );
Obtiene el nombre de la conexión en tu búfer, que tiene al menos nMaxLen bytes. Devuelve false si el handle no es válido.

ConfigureConnectionLanes

EResult ConfigureConnectionLanes( HSteamNetConnection hConn, int nNumLanes, const int *pLanePriorities, const uint16 *pLaneWeights );

Configura varias retransmisiones de mensajes salientes (líneas) en una conexión y controla el bloqueo de cabeza de líneas («HOL blocking» en inglés) entre sí. Los mensajes de una línea determinada siempre se envían en el orden en el que se pusieron en cola, pero los mensajes de diferentes líneas pueden enviarse de forma desordenada. Cada línea tiene su propia secuencia de números de mensajes. Se asignará el número 1 al primer mensaje enviado en cada línea.

Cada línea tiene una prioridad determinada. Las líneas de menor prioridad solo se procesarán cuando todas las líneas de mayor prioridad estén vacías. Las magnitudes de los valores de prioridad no son relevantes, solo lo es el orden de clasificación. Los valores numéricos más altos tienen prioridad sobre los valores más bajos.

A cada línea se le asigna también un peso, que controla la proporción aproximada del ancho de banda que consumirá la línea y es relativo a otras líneas de la misma prioridad. Esta situación se dará si la línea permanece ocupada. Una línea inactiva no acumula créditos para gastar una vez que un mensaje se pone en cola. Este valor solo es significativo como una proporción relativa a las otras líneas con la misma prioridad. En las líneas con diferentes prioridades prevalecerá el orden de prioridad estricto, y sus pesos relativos no serán relevantes entre sí. Por lo tanto, si la línea tiene un valor de prioridad único, el valor del peso de esa línea no será relevante.

Ejemplo: 3 líneas con prioridades { 0, 10, 10 } y pesos { (NA), 20, 5 }. Los mensajes enviados en la primera línea siempre se enviarán antes que los mensajes en las otras dos líneas. El valor de su peso es irrelevante, ya que no hay ninguna otra línea con un valor de prioridad equivalente a 0. Las otras dos líneas compartirán el ancho de banda. La segunda y tercera línea se dividirán el ancho de banda utilizando una relación aproximada de 4:1. Los pesos { NA, 4, 1 } serían equivalentes.

Notas:
  • En este momento, algunos códigos tienen un coste de rendimiento proporcional al número de líneas, así intenta tener el menor número posible de líneas. No pasa nada por tener alrededor de 3 líneas, pero 8 son demasiadas. El número máximo de líneas en Steam es 255, un número demasiado grande que no recomendamos.
  • Los valores de prioridad de las líneas pueden ser cualquier número entero. Su valor absoluto no es relevante, solo importa el orden.
  • El peso debe ser positivo y, debido a la implementación de detalles, está restringido a un valor de 16 bits. No importan las magnitudes absolutas, solo las proporciones.
  • Los mensajes enviados en un índice de línea que tengan un valor distinto a 0 tienen un pequeño sobrecoste en el cable, así que para obtener una eficiencia de cable máxima, la línea con valor 0 debería ser la línea más común, independientemente del peso o la prioridad.
  • Una conexión tiene una sola línea de manera predeterminada. Es legal llamar a esta función con nNumLanes=1, pero es inútil porque los valores de peso y prioridad son irrelevantes en ese caso.
  • Puedes reconfigurar las líneas de conexión en cualquier momento, pero no se puede reducir el número de líneas.
  • Puede que la reconfiguración de las líneas reinicie cualquier equilibrio del uso compartido del ancho de banda. Por lo general llamarás a esta función una vez, cerca del inicio de la conexión, o quizás después de intercambiar algunos mensajes.
  • Puedes usar pLanePriorities=NULL para asignar la misma prioridad a todas las líneas.
  • Si quieres que todas las líneas con la misma prioridad compartan el ancho de banda de manera equitativa (o si no hay líneas con el mismo valor de prioridad y, por lo tanto, los valores son irrelevantes), puedes usar pLaneWeights=NULL.
  • La prioridad y el peso determinan el orden en el que los mensajes se envían en el cable. ¡No se puede garantizar el orden en el que se recibirán los mensajes! Debido a la pérdida de paquetes, las entregas desordenadas y los detalles sutiles de la serialización de los paquetes, puede que los mensajes se sigan recibiendo ligeramente desordenados. La única garantía sólida es que los mensajes fiables en la misma línea se entregarán en el orden en el que se envíen.
  • Cada host configura las líneas de los paquetes que envía; las líneas que fluyen en una dirección no tienen ninguna relación con las líneas que van en la dirección opuesta.

Valores devueltos:
  • k_EResultNoConnection: hConn incorrecto.
  • k_EResultInvalidParam: el número de líneas no es válido, el peso es incorrecto o intentaste reducir el número de líneas.
  • k_EResultInvalidState: la conexión ya está muerta, etc.

Véase también:
  • SteamNetworkingMessage_t::m_idxLane

Otros

GetListenSocketAddress

bool GetListenSocketAddress( HSteamListenSocket hSocket, SteamNetworkingIPAddr *address );

Devuelve la IP local y el puerto al que está enlazado un socket de escucha creado con CreateListenSocketIP.

Se pueden devolver direcciones IPv6/IPv4 específicas si enlazas el socket a una interfaz en particular.
Una dirección IPv6 de ::0 significa «cualquier IPv4 o IPv6»
Una dirección IPv6 de ::ffff:0000:0000 significa «cualquier IPv4».

NOTA: Esta no es la forma en que encuentras tu dirección IP pública a la que los clientes pueden conectarse.
Prueba ISteamGameServer::GetPublicIP.

Devuelve false si el handle no es válido o si la información no está disponible para ese tipo de socket de escucha.

GetIdentity

bool GetIdentity( SteamNetworkingIdentity *pIdentity );
Obtiene la identidad asignada a esta interfaz.

P.ej. en Steam, este es el SteamID del usuario, o en la interfaz del servidor de juegos, el SteamID asignado al servidor de juegos. Devuelve false y establece el resultado como una identidad no válida si aún no conocemos nuestra identidad. Por ejemplo, GameServer no ha iniciado sesión. En Steam, el usuario sabrá su SteamID incluso si no ha iniciado sesión en Steam.

InitAuthentication

ESteamNetworkingAvailability InitAuthentication();

Indica nuestro deseo de estar preparados para participar en comunicaciones autenticadas. Si actualmente no estamos listos, se tomarán medidas para obtener los certificados necesarios. Esto incluye un certificado para nosotros, así como también cualquier certificado de CA necesario para autenticar los pares.

Puedes realizar esta llamada en el momento de inicio del programa si sabes que vas a hacer conexiones autenticadas, así estaremos listos de inmediato cuando se intenten esas conexiones. Ten en cuenta que esencialmente todas las conexiones requieren autenticación, excepto las conexiones UDP normales que usen k_ESteamNetworkingConfig_IP_AllowWithoutAuth y que tengan la autenticación deshabilitada. Si no llamas a esta función, esperaremos hasta que se utilice una función que requiera estos recursos.

También puedes llamar a esta función para forzar un nuevo intento si se ha producido un error. Una vez que hacemos un intento y fallamos, no volveremos a intentarlo automáticamente. A este respecto, el comportamiento del sistema después de intentarlo y fallar es el mismo que antes del primer intento: intentar la comunicación autenticada o al llamar a esta función se llamará al sistema para intentar adquirir los recursos necesarios.

Puedes usar GetAuthenticationStatus o estar a la espera para detectar SteamNetAuthenticationStatus_t y monitorizar el estado.

Devuelve el valor actual que se devolvería desde GetAuthenticationStatus.

GetAuthenticationStatus

ESteamNetworkingAvailability GetAuthenticationStatus( SteamNetAuthenticationStatus_t *pDetails );

Consulta nuestra disponibilidad para participar en comunicaciones autenticadas. Una función callback SteamNetAuthenticationStatus_t se publica cada vez que este estado cambia, pero puedes usar esta función para consultarlo en cualquier momento.

Devuelve el valor de SteamNetAuthenticationStatus_t::m_eAvail. Si solo quieres este estado general, puedes pasar NULL para pDetails. Si quieres más detalles, pasa non-NULL para recibirlos.

Servidores de juego que usan Steam Datagram Relay (SDR)

Las siguientes funciones se utilizan cuando tu servidor de juego está en un centro de datos que Valve conoce y el tráfico del juego aprovecha la red Steam Datagram Relay. Para obtener más información, consulta Steam Datagram Relay.

ReceivedRelayAuthTicket

bool ReceivedRelayAuthTicket( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutParsedTicket );

Realiza esta llamada cuando recibas un ticket de tu sistema backend o de emparejamiento. Coloca el ticket en una caché persistente y, opcionalmente, devuelve el ticket analizado.

Consulta stamdatagram_gamecoordinator.h para obtener más detalles.

FindRelayAuthTicketForServer

int FindRelayAuthTicketForServer( const SteamNetworkingIdentity &identityGameServer, int nRemoteVirtualPort, SteamDatagramRelayAuthTicket *pOutParsedTicket );

Busca en la memoria caché un ticket para comunicarse con el servidor en el puerto virtual especificado. Si lo encuentra, devuelve el número de segundos hasta que caduque el ticket y, opcionalmente, el ticket completo descifrado. Devuelve 0 si no tenemos un ticket.

Por lo general, esto es útil solo para confirmar que tienes un ticket, antes de llamar a ConnectToHostedDedicatedServer para conectarse al servidor.

ConnectToHostedDedicatedServer

HSteamNetConnection ConnectToHostedDedicatedServer( const SteamNetworkingIdentity &identityTarget, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions );

Llamada del cliente para conectarse a un servidor alojado en un centro de datos de Valve, en el puerto virtual especificado. Debes haber colocado un ticket para este servidor en la memoria caché, de lo contrario este intento de conexión fallará. Si no estás emitiendo tus propios tickets, conéctate al servidor dedicado a través de SDR en modo de tickets automáticos y utiliza ConnectP2P. El servidor debe estar configurado para permitir este tipo de conexión de escucha con CreateListenSocketP2P.

Seguramente te preguntes por qué los tickets se almacenan en una caché, en lugar de simplemente pasarse como un argumento aquí. Al almacenarse de esta manera, la reconexión a un servidor de juegos es más robusta, incluso si el ordenador del cliente pierde la conexión a Steam o al backend central, o la aplicación se reinicia o se bloquea, etc.

Si optas por esta opción, te recomendamos que llames a ISteamNetworkingUtils::InitRelayNetworkAccess cuando tu aplicación se inicie.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

GetHostedDedicatedServerPort

uint16 GetHostedDedicatedServerPort();
Devuelve el valor de la variable de entorno SDR_LISTEN_PORT. Este es el servidor UDP en el que escuchará tu servidor. Esto se configurará automáticamente para ti en entornos de producción.

Mientras está en desarrollo, deberás configurarlo tú mismo. Consulta Steam Datagram Relay para obtener más información sobre cómo configurar entornos de desarrollo.

GetHostedDedicatedServerPOPID

SteamNetworkingPOPID GetHostedDedicatedServerPOPID();
Devuelve 0 si SDR_LISTEN_PORT no está configurado. De lo contrario, devuelve el centro de datos en el que se ejecuta el servidor, que será k_SteamDatagramPOPID_dev en un entorno que no sea de producción.

GetHostedDedicatedServerAddress

EResult GetHostedDedicatedServerAddress( SteamDatagramHostedAddress *pRouting );
Devuelve información sobre el servidor alojado. Contiene el PoPID del servidor y la información de enrutamiento opaca que puede ser utilizada por las retransmisiones para enviar tráfico a tu servidor.

Necesitarás enviar esta información a tu backend y ponerla en tickets, para que las retransmisiones sepan cómo reenviar el tráfico de los clientes a tu servidor. Consulta SteamDatagramRelayAuthTicket para obtener más información.

Además, ten en cuenta que la información de enrutamiento está contenida en SteamDatagramGameCoordinatorServerLogin, por lo que si es posible, es preferible usar SteamNetworkingSockets::GetGameCoordinatorServerLogin para enviar esta información a tu servicio de coordinación del juego, y también para iniciar sesión de forma segura al mismo tiempo.

En una salida efectuada correctamente, devuelve k_EResultOK.

Salida fallida:
  • Devuelve algo distinto a k_EResultOK.
  • k_EResultInvalidState: no tenemos la configuración para detectar SDR (SDR_LISTEN_SOCKET no está configurado).
  • k_EResultPending: No tenemos (todavía) la información de autenticación necesaria. Consulta GetAuthenticationStatus. Si utilizas variables de entorno para precargar la configuración de la red, estos datos siempre deberían estar disponibles de inmediato.
  • Se pondrá un mensaje de depuración de diagnóstico sin traducir en m_data que describe la causa del fallo.

NOTA: El blob que se devuelve no está cifrado. Envíalo a tu backend, pero no lo compartas directamente con los usuarios.

CreateHostedDedicatedServerListenSocket

HSteamListenSocket CreateHostedDedicatedServerListenSocket( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions );
Crea un socket de escucha en el puerto virtual especificado. El puerto UDP físico que se va a usar será determinado por la variable de entorno SDR_LISTEN_PORT. Si un puerto UDP no está configurado, esta llamada fallará.

Ten en cuenta que esta llamada DEBE realizarse a través de la interfaz SteamGameServerNetworkingSockets().

Deberías usar esta función cuando estés usando la biblioteca generadora de tickets para emitir tus propios tickets. Los usuarios que se conecten al servidor en este puerto virtual necesitarán un ticket y deben conectarse usando ConnectToHostedDedicatedServer.

Si necesitas establecer alguna opción de configuración inicial, pásala aquí. Consulta SteamNetworkingConfigValue_t para obtener más información sobre por qué esto es mejor que configurar las opciones inmediatamente después de la creación.

GetGameCoordinatorServerLogin

EResult GetGameCoordinatorServerLogin( SteamDatagramGameCoordinatorServerLogin *pLoginInfo, int *pcbSignedBlob, void *pBlob );

Genera un blob de autenticación que puede usarse para iniciar sesión de forma segura con tu backend, utilizando SteamDatagram_ParseHostedServerLogin. Consulta steamdatagram_gamecoordinator.h.

Antes de llamar a la función:
  • Rellena los datos de la aplicación en pLoginInfo (m_cbAppData y m_appData). Puedes dejar todos los demás campos sin inicializar.
  • *pcbSignedBlob contiene el tamaño del búfer en pBlob. Debería ser al menos k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.

En una salida efectuada correctamente:
  • Devuelve k_EResultOK.
  • Se completarán todos los campos restantes de pLoginInfo.
  • *pcbSignedBlob contiene el tamaño del blob serializado que se ha colocado en pBlob.

Salida fallida:
  • Devuelve algo distinto a k_EResultOK.
  • k_EResultNotLoggedOn: no has iniciado sesión (todavía).
  • Consulta ISteamNetwrokingSockets::GetHostedDedicatedServerAddress para otros posibles valores devueltos en caso de error.
  • Se pondrá un mensaje de depuración de diagnóstico sin traducir en pBlob que describe la causa del fallo.

Esto funciona firmando el contenido de SteamDatagramGameCoordinatorServerLogin con el certificado que se emite a este servidor. En entornos de desarrollo, está BIEN si no tienes un certificado. Deberías habilitar el inicio de sesión de desarrollador no seguro en SteamDatagram_ParseHostedServerLogin.
De lo contrario, necesitarás un certificado firmado.

NOTA: El blob de enrutamiento devuelto aquí no está cifrado. Envíalo a tu backend y no lo compartas directamente con los usuarios.

Sistema FakeIP


Un FakeIP es básicamente un identificador aleatorio temporal que además resulta ser una dirección IPv4 válida. La finalidad de este sistema es facilitar la integración con el código existente que detecta los hosts que utilizan direcciones IPv4. La dirección IP falsa (o FakeIP) nunca se utilizará para enviar o recibir paquetes en internet; es exclusivamente un identificador.

Las direcciones IP falsas están diseñadas para (con suerte) pasar el código existente de la manera más transparente posible y entrar en conflicto lo menos posible con las direcciones reales que podrían estar en uso en las redes (tanto internet como redes de área local) en el mismo código. En el momento en que redactamos este artículo, proceden del rango 169.254.0.0/16 y el número de puerto es siempre mayor que 1024. SIN EMBARGO, esto puede cambiar. No hagas suposiciones acerca de estas direcciones para evitar que tu código falle. En concreto, utiliza funciones como ISteamNetworkingUtils::IsFakeIP para establecer si una dirección IP es una dirección falsa utilizada por este sistema.

BeginAsyncRequestFakeIP

bool BeginAsyncRequestFakeIP( int nNumPorts );

Comienza el proceso asincrónico de asignación de una dirección IPv4 falsa que otros pares pueden usar para ponerse en contacto con nosotros mediante P2P. Las direcciones IP que devuelve esta función son únicas a nivel global para un determinado id. de aplicación.

nNumports es el número de puertos que quieres reservar. Esto es útil por la misma razón por la que escuchar en varios puertos UDP es útil para diferentes tipos de tráfico. Puesto que estas asignaciones provienen de un espacio de nombres global, hay un límite relativamente estricto en la cantidad máxima de puertos que puedes solicitar. En el momento de escribir este artículo, el límite es 4. ¡No se garantiza que las asignaciones de puertos tengan un orden o relación en particular! No des por sentado que son contiguos, aunque suelen serlo en la práctica.

Devuelve false si ya había una solicitud en curso y true si se inició una nueva solicitud. Cuando se completa la solicitud, se activa la función SteamNetworkingFakeIPResult_t.

En el caso de los servidores de juegos, es necesario realizar la llamada después de inicializar el SDK pero antes de iniciar sesión. Steam necesita saber de antemano que se utilizará FakeIP. En donde aparezca normalmente tu dirección IP pública (como el explorador de servidores), se reemplazará por la dirección IP falsa y el puerto falso en el índice 0. De hecho, la solicitud está en cola hasta que finaliza el inicio de sesión, por lo que no debes esperar a que finalice la asignación para iniciar sesión. A excepción de los errores triviales que se pueden detectar localmente (por ejemplo, un parámetro no válido), no se publicará una función callback SteamNetworkingFakeIPResult_t (ya sea correcta o fallida) hasta que hayamos iniciado sesión. Además, se supone que la asignación de FakeIP es esencial para que tu aplicación funcione, por lo que no se notificará el error hasta que se hayan realizado varios intentos. Este proceso puede durar varios minutos. Se recomienda encarecidamente tratar los fallos como errores irrecuperables.

Para comunicarse mediante una API orientada a conexiones (estilo TCP):
  • El servidor crea un socket de escucha mediante CreateListenSocketP2PFakeIP.
  • El cliente se conecta mediante ConnectByIPAddress, pasando la dirección IP falsa.
  • La conexión funcionará prácticamente igual que una conexión P2P. Las identidades que aparecen en SteamNetConnectionInfo_t serán la identidad IP falsa hasta que conozcamos la identidad real. Después será la identidad real. Si SteamNetConnectionInfo_t::m_addrRemote es válida, será una dirección IPv4 real de una conexión mediante perforación NAT. De lo contrario, no será válida.

Para comunicarse usando una API ad-hoc sendto/recv from (estilo UDP), utiliza CreateFakeUDPPort.

GetFakeIP

void GetFakeIP( int idxFirstPort, SteamNetworkingFakeIPResult_t *pInfo );

Devuelve información sobre la dirección IP falsa y los puertos que nos han asignado, si los hay. idxFirstPort está reservado actualmente y debe ser cero. Asegúrate de comprobar SteamNetworkingFakeIPResult_t::m_eResult.

CreateListenSocketP2PFakeIP

HSteamListenSocket CreateListenSocketP2PFakeIP( int idxFakePort, int nOptions, const SteamNetworkingConfigValue_t *pOptions );

Crea un socket de escucha que detecta conexiones P2P enviadas a nuestro FakeIP. Los pares pueden iniciar conexiones con este socket de escucha llamando a ConnectByIPAddress.

idxFakePort hace referencia al índice del puerto falso solicitado, no al número de puerto real. Por ejemplo, pasa 0 para hacer referencia al primer puerto de la reserva. Realiza esta llamada solamente después de llamar a BeginAsyncRequestFakeIP. Sin embargo, no es necesario esperar a que se complete la solicitud para crear el socket de escucha.

GetRemoteFakeIPForConnection

EResult GetRemoteFakeIPForConnection( HSteamNetConnection hConn, SteamNetworkingIPAddr *pOutAddr );

Si la conexión se inició utilizando el sistema FakeIP, podemos obtener una dirección IP para el host remoto. Si el host remoto tenía un FakeIP global en el momento en que se estableció la conexión, esta función devolverá esa dirección IP global. De lo contrario, se asignará y devolverá un FakeIP único a nivel local desde el espacio de direcciones FakeIP locales.

La asignación de direcciones IP falsas locales intenta asignar direcciones de forma consistente. Si se realizan varias conexiones al mismo host remoto, probablemente devolverán la misma dirección IP falsa. Sin embargo, dado que el espacio de nombres es limitado, no se puede garantizar.

En caso de error, devuelve:
  • k_EResultInvalidParam: handle de conexión incorrecto.
  • k_EResultIPNotFound: no se usó el sistema FakeIP para esta conexión.

CreateFakeUDPPort

ISteamNetworkingFakeUDPPort *CreateFakeUDPPort( int idxFakeServerPort );

Obtiene una interfaz que puede usarse como un puerto UDP para enviar o recibir datagramas a una dirección IP falsa. El objetivo es facilitar la migración del código basado en UDP existente para sacar partido a SDR.

idxFakeServerPort hace referencia al índice del puerto asignado mediante BeginAsyncRequestFakeIP y se utiliza para crear puertos de servidor. Puedes llamar a esta función antes de que haya finalizado la asignación. Sin embargo, cualquier intento de envío de paquetes fallará hasta que la asignación se haya realizado correctamente. Cuando el par recibe paquetes enviados desde esta interfaz, la dirección de origen del paquete será la dirección IP falsa única de forma global. Si llamas a esta función varias veces y pasas el mismo índice de puerto falso (no negativo), se devolverá el mismo objeto y no se contará por referencia a este objeto.

Para crear un puerto de cliente (por ejemplo, el equivalente a un puerto UDP efímero), pasa -1. En este caso, se devolverá un objeto distinto para cada llamada. Cuando el par recibe los paquetes enviados desde esta interfaz, el par asignará una dirección IP falsa desde su propio espacio de nombres controlado localmente.

Estructuras de funciones callback

SteamNetConnectionStatusChangedCallback_t

Esta función callback se activa cada vez que se crea, destruye o cambia el estado de una conexión. El campo m_info contendrá una descripción completa de la conexión en el momento en que se produjo el cambio y se activó la función callback. En particular, m_info.m_eState tendrá el nuevo estado de conexión.

Por lo general, deberás fijarte en esta función callback para saber cuándo:
  • Se establece una nueva conexión en un socket de escucha. Se establecerá m_info.m_hListenSocket, m_eOldState = k_ESteamNetworkingConnectionState_None y m_info.m_eState = k_ESteamNetworkingConnectionState_Connecting. Consulta AcceptConnection.
  • El host remoto ha aceptado una conexión que iniciaste. m_eOldState = k_ESteamNetworkingConnectionState_Connecting y m_info.m_eState = k_ESteamNetworkingConnectionState_Connected. Algunas conexiones pueden hacer la transición primero a k_ESteamNetworkingConnectionState_FindingRoute.
  • El host remoto ha rechazado o cerrado activamente una conexión. m_eOldState = k_ESteamNetworkingConnectionState_Connecting o k_ESteamNetworkingConnectionState_Connected y m_info.m_eState = k_ESteamNetworkingConnectionState_ClosedByPeer. m_info.m_eEndReason y m_info.m_szEndDebug ofrecen más detalles. NOTA: al recibir esta función callback, aún debes destruir la conexión usando CloseConnection para liberar recursos locales. Los detalles pasados a la función no se utilizan en este caso, ya que la conexión ya está cerrada.
  • Se detectó un problema con la conexión y el host local la ha cerrado. El problema más común es el tiempo de espera, pero también pueden aparecer otros problemas de configuración o autenticación. m_eOldState = k_ESteamNetworkingConnectionState_Connecting o k_ESteamNetworkingConnectionState_Connected, y m_info.m_eState = k_ESteamNetworkingConnectionState_ProblemDetectedLocally. m_info.m_eEndReason y m_info.m_szEndDebug ofrecen más detalles. NOTA: al recibir esta función callback, aún debes destruir la conexión usando CloseConnection para liberar recursos locales. Los detalles pasados a la función no se utilizan en este caso, ya que la conexión ya está cerrada.

Recuerda que las funciones callback se envían a una cola y las conexiones de red pueden cambiar en cualquier momento. Es posible que la conexión ya haya cambiado de estado en el momento en que procesas esta función callback.

Ten en cuenta también que las funciones callback se activarán cuando sus propias llamadas a la API creen y destruyan las conexiones.

struct SteamNetConnectionStatusChangedCallback_t { /// Handle de conexión HSteamNetConnection m_hConn; /// Información completa de la conexión SteamNetConnectionInfo_t m_info; /// Estado anterior. (El estado actual está en in m_info.m_eState) ESteamNetworkingConnectionState m_eOldState; };

SteamNetAuthenticationStatus_t


Una estructura utilizada para describir nuestra disposición a participar en comunicaciones autenticadas y cifradas. Para ello necesitamos:
  • La lista de certificados de CA de confianza que pueden ser relevantes para esta aplicación.
  • Un certificado válido emitido por una CA.

Esta función callback se activa cada vez que cambia el estado de nuestra disposición a participar.

struct SteamNetAuthenticationStatus_t { /// Estado ESteamNetworkingAvailability m_eAvail; /// Estado del idioma inglés sin traducir. Solo para fines/debugging /// de diagnóstico. char m_debugMsg[]; };

Señalización P2P personalizada

Señalización se refiere a los mensajes de encuentro enviados a través de un canal de confianza que es de bajo ancho de banda y latencia alta, utilizado por pares para negociar una conexión P2P. Steam te proporciona un servicio de señalización. Sin embargo, en algunas situaciones, es posible que quieras hacer tu propia señalización. Por ejemplo, si uno o ambos de tus pares no están en Steam. Puedes usar SteamNetworkingSockets para establecer conexiones P2P con tu propia señalización. Puedes usar ICE para pasar a través de NAT y usar los servidores estándar STUN/TURN o, dependiendo de tu situación, puede que la red de retransmisión SDR y la red troncal de Valve no estén disponibles. Por favor, avísanos si necesitas más información sobre estas API.