net topic

CategorySDLNet

SDL_net is a simple library to help with networking.

In current times, it's a relatively thin layer over system-level APIs like BSD Sockets or WinSock. It's primary strength is in making those interfaces less complicated to use, and handling several unexpected corner cases, so the app doesn't have to.

Some design philosophies of SDL_net:

  • Nothing is blocking (but you can explicitly wait on things if you want).
  • Addressing is abstract so you don't have to worry about specific networks and their specific protocols.
  • Simple is better than hard, and not necessarily less powerful either.

There are several pieces to this library, and most apps won't use them all, but rather choose the portion that's relevant to their needs.

All apps will call NET_Init() on startup and NET_Quit() on shutdown.

The cornerstone of the library is the NET_Address object. This is what manages the details of how to reach another computer on the network, and what network protocol to use to get there. You'll need a NET_Address to talk over the network. If you need to convert a hostname (such as "google.com" or "libsdl.org") into a NET_Address, you can call NET_ResolveHostname(), which will do the appropriate DNS queries on a background thread. Once these are ready, you can use the NET_Address to connect to these hosts over the Internet.

Something that initiates a connection to a remote system is called a "client," connecting to a "server." To establish a connection, use the NET_Address you resolved with NET_CreateClient(). Once the connection is established (a non-blocking operation), you'll have a NET_StreamSocket object that can send and receive data over the connection, using NET_WriteToStreamSocket() and NET_ReadFromStreamSocket().

To instead be a server, that clients connect to, call NET_CreateServer() to get a NET_Server object. All a NET_Server does is allow you to accept connections from clients, turning them into NET_StreamSockets, where you can read and write from the opposite side of the connection from a given client.

These things are, underneath this API, TCP connections, which means you can use a client or server to talk to something that isn't using SDL_net at all.

Clients and servers deal with "stream sockets," a reliable stream of bytes. There are tradeoffs to using these, especially in poor network conditions. Another option is to use "datagram sockets," which map to UDP packet transmission. With datagrams, everyone involved can send small packets of data that may arrive in any order, or not at all, but transmission can carry on if a packet is lost, each packet is clearly separated from every other, and communication can happen in a peer-to-peer model instead of client-server: while datagrams can be more complex, these are useful properties not avaiable to stream sockets. NET_CreateDatagramSocket() is used to prepare for datagram communication, then NET_SendDatagram() and NET_ReceiveDatagram() transmit packets.

As previously mentioned, SDL_net's API is "non-blocking" (asynchronous). Any network operation might take time, but SDL_net's APIs will not wait until they complete. Any operation will return immediately, with options to check if the operation has completed later. Generally this is what a video game needs, but there are times where it makes sense to pause until an operation completes; in a background thread this might make sense, as it could simplify the code dramatically.

The functions that block until an operation completes:

  • NET_WaitUntilConnected
  • NET_WaitUntilInputAvailable
  • NET_WaitUntilResolved
  • NET_WaitUntilStreamSocketDrained

All of these functions offer a timeout, which allow for a maximum wait time, an immediate non-blocking query, or an infinite wait.

Finally, SDL_net offers a way to simulate network problems, to test the always-less-than-ideal conditions in the real world. One can programmatically make the app behave like it's on a flakey wifi connection even if it's running wired directly to a gigabit fiber line. The functions:

  • NET_SimulateAddressResolutionLoss
  • NET_SimulateStreamPacketLoss
  • NET_SimulateDatagramPacketLoss

Functions

netAcceptClient(Pointer<NetServer> server, Pointer<Pointer<NetStreamSocket>> clientStream) bool net
Create a stream socket for the next pending client connection.
netCompareAddresses(Pointer<NetAddress> a, Pointer<NetAddress> b) int net
Compare two NET_Address objects.
netCreateClient(Pointer<NetAddress> address, int port) Pointer<NetStreamSocket> net
Begin connecting a socket as a client to a remote server.
netCreateDatagramSocket(Pointer<NetAddress> addr, int port) Pointer<NetDatagramSocket> net
Create and bind a new datagram socket.
netCreateServer(Pointer<NetAddress> addr, int port) Pointer<NetServer> net
Create a server, which listens for connections to accept.
netDestroyDatagram(Pointer<NetDatagram> dgram) → void net
Dispose of a datagram packet previously received.
netDestroyDatagramSocket(Pointer<NetDatagramSocket> sock) → void net
Dispose of a previously-created datagram socket.
netDestroyServer(Pointer<NetServer> server) → void net
Dispose of a previously-created server.
netDestroyStreamSocket(Pointer<NetStreamSocket> sock) → void net
Dispose of a previously-created stream socket.
netFreeLocalAddresses(Pointer<Pointer<NetAddress>> addresses) → void net
Free the results from NET_GetLocalAddresses.
netGetAddressStatus(Pointer<NetAddress> address) int net
Check if an address is resolved, without blocking.
netGetAddressString(Pointer<NetAddress> address) String? net
Get a human-readable string from a resolved address.
netGetConnectionStatus(Pointer<NetStreamSocket> sock) int net
Check if a stream socket is connected, without blocking.
netGetLocalAddresses(Pointer<Int32> numAddresses) Pointer<Pointer<NetAddress>> net
Obtain a list of local addresses on the system.
netGetStreamSocketAddress(Pointer<NetStreamSocket> sock) Pointer<NetAddress> net
Get the remote address of a stream socket.
netGetStreamSocketPendingWrites(Pointer<NetStreamSocket> sock) int net
Query bytes still pending transmission on a stream socket.
netInit() bool net
Initialize the SDL_net library.
netQuit() → void net
Deinitialize the SDL_net library.
netReadFromStreamSocket(Pointer<NetStreamSocket> sock, Pointer<NativeType> buf, int buflen) int net
Receive bytes that a remote system sent to a stream socket.
netReceiveDatagram(Pointer<NetDatagramSocket> sock, Pointer<Pointer<NetDatagram>> dgram) bool net
Receive a new packet that a remote system sent to a datagram socket.
netRefAddress(Pointer<NetAddress> address) Pointer<NetAddress> net
Add a reference to an NET_Address.
netResolveHostname(String? host) Pointer<NetAddress> net
Resolve a human-readable hostname.
netSendDatagram(Pointer<NetDatagramSocket> sock, Pointer<NetAddress> address, int port, Pointer<NativeType> buf, int buflen) bool net
Send a new packet over a datagram socket to a remote system.
netSimulateAddressResolutionLoss(int percentLoss) → void net
Enable simulated address resolution failures.
netSimulateDatagramPacketLoss(Pointer<NetDatagramSocket> sock, int percentLoss) → void net
Enable simulated datagram socket failures.
netSimulateStreamPacketLoss(Pointer<NetStreamSocket> sock, int percentLoss) → void net
Enable simulated stream socket failures.
netUnrefAddress(Pointer<NetAddress> address) → void net
Drop a reference to an NET_Address.
netVersion() int net
This function gets the version of the dynamically linked SDL_net library.
netWaitUntilConnected(Pointer<NetStreamSocket> sock, int timeout) int net
Block until a stream socket has connected to a server.
netWaitUntilInputAvailable(Pointer<Pointer<NativeType>> vsockets, int numsockets, int timeout) int net
Block on multiple sockets until at least one has data available.
netWaitUntilResolved(Pointer<NetAddress> address, int timeout) int net
Block until an address is resolved.
netWaitUntilStreamSocketDrained(Pointer<NetStreamSocket> sock, int timeout) int net
Block until all of a stream socket's pending data is sent.
netWriteToStreamSocket(Pointer<NetStreamSocket> sock, Pointer<NativeType> buf, int buflen) bool net
Send bytes over a stream socket to a remote system.