|
SDL3pp
A slim C++ wrapper for SDL3
|
SDL_net is a simple library to help with networking. More...
Namespaces | |
| namespace | SDL::prop |
| Constants for Properties keys. | |
Classes | |
| struct | SDL::AddressBase |
| Base class to Address. More... | |
| struct | SDL::Address |
| Opaque representation of a computer-readable network address. More... | |
| struct | SDL::StreamSocketBase |
| Base class to StreamSocket. More... | |
| struct | SDL::StreamSocket |
| An object that represents a streaming connection to another system. More... | |
| struct | SDL::ServerBase |
| Base class to Server. More... | |
| struct | SDL::Server |
| The receiving end of a stream connection. More... | |
| struct | SDL::DatagramSocketBase |
| Base class to DatagramSocket. More... | |
| struct | SDL::DatagramSocket |
| An object that represents a datagram connection to another system. More... | |
| struct | SDL::DatagramBase |
| Base class to Datagram. More... | |
| struct | SDL::Datagram |
| The data provided for new incoming packets from ReceiveDatagram(). More... | |
Macros | |
| #define | SDL_NET_MAJOR_VERSION |
| The current major version of the SDL_net headers. | |
| #define | SDL_NET_MINOR_VERSION |
| The current minor version of the SDL_net headers. | |
| #define | SDL_NET_MICRO_VERSION |
| The current micro (or patchlevel) version of the SDL_net headers. | |
| #define | SDL_NET_VERSION |
| This is the version number macro for the current SDL_net version. | |
| #define | SDL_NET_VERSION_ATLEAST(X, Y, Z) |
| This macro will evaluate to true if compiled with SDL_net at least X.Y.Z. | |
Typedefs | |
| using | SDL::AddressRaw = NET_Address* |
| Alias to raw representation for Address. | |
| using | SDL::AddressRef = ResourceRefT<AddressBase> |
| Reference for Address. | |
| using | SDL::StreamSocketRaw = NET_StreamSocket* |
| Alias to raw representation for StreamSocket. | |
| using | SDL::StreamSocketRef = ResourceRefT<StreamSocketBase> |
| Reference for StreamSocket. | |
| using | SDL::ServerRaw = NET_Server* |
| Alias to raw representation for Server. | |
| using | SDL::ServerRef = ResourceRefT<ServerBase> |
| Reference for Server. | |
| using | SDL::DatagramSocketRaw = NET_DatagramSocket* |
| Alias to raw representation for DatagramSocket. | |
| using | SDL::DatagramSocketRef = ResourceRefT<DatagramSocketBase> |
| Reference for DatagramSocket. | |
| using | SDL::DatagramRaw = NET_Datagram* |
| Alias to raw representation for Datagram. | |
| using | SDL::DatagramRawConst = const NET_Datagram* |
| Alias to const raw representation for Datagram. | |
| using | SDL::DatagramRef = ResourceRefT<DatagramBase> |
| Reference for Datagram. | |
| using | SDL::DatagramConstRef = ResourceConstRef<DatagramRaw, DatagramRawConst> |
| Safely wrap Datagram for non owning const parameters. | |
| using | SDL::Status = NET_Status |
| A tri-state for asynchronous operations. | |
| using | SDL::LocalAddressesArray = OwnArray<AddressRef, LocalAddressesArrayDeleter> |
| Array of addresses returned by GetLocalAddresses. | |
Functions | |
| Address | SDL::ResolveHostname (StringParam host) |
| Resolve a human-readable hostname. | |
| Status | SDL::WaitUntilResolved (AddressRef address, Sint32 timeout) |
| Block until an address is resolved. | |
| Status | SDL::GetAddressStatus (AddressRef address) |
| Check if an address is resolved, without blocking. | |
| const char * | SDL::GetAddressString (AddressRef address) |
| Get a human-readable string from a resolved address. | |
| const void * | SDL::GetAddressBytes (AddressRef address, int *num_bytes) |
| Get the protocol-level bytes of a network address from a resolved address. | |
| Address | SDL::RefAddress (AddressRef address) |
| Add a reference to an Address. | |
| void | SDL::UnrefAddress (AddressRaw address) |
| Drop a reference to an Address. | |
| void | SDL::SimulateAddressResolutionLoss (int percent_loss) |
| Enable simulated address resolution failures. | |
| int | SDL::CompareAddresses (AddressRef a, AddressRef b) |
| Compare two Address objects. | |
| LocalAddressesArray | SDL::GetLocalAddresses () |
| Obtain a list of local addresses on the system. | |
| void | SDL::FreeLocalAddresses (AddressRef *addresses) |
| Free the results from GetLocalAddresses. | |
| StreamSocket | SDL::CreateClient (AddressRef address, Uint16 port, PropertiesRef props) |
| Begin connecting a socket as a client to a remote server. | |
| Status | SDL::WaitUntilConnected (StreamSocketRef sock, Sint32 timeout) |
| Block until a stream socket has connected to a server. | |
| Server | SDL::CreateServer (AddressRef addr, Uint16 port, PropertiesRef props) |
| Create a server, which listens for connections to accept. | |
| void | SDL::AcceptClient (ServerRef server, NET_StreamSocket **client_stream) |
| Create a stream socket for the next pending client connection. | |
| void | SDL::DestroyServer (ServerRaw server) |
| Dispose of a previously-created server. | |
| Address | SDL::GetStreamSocketAddress (StreamSocketRef sock) |
| Get the remote address of a stream socket. | |
| Status | SDL::GetConnectionStatus (StreamSocketRef sock) |
| Check if a stream socket is connected, without blocking. | |
| bool | SDL::WriteToStreamSocket (StreamSocketRef sock, const void *buf, int buflen) |
| Send bytes over a stream socket to a remote system. | |
| int | SDL::GetStreamSocketPendingWrites (StreamSocketRef sock) |
| Query bytes still pending transmission on a stream socket. | |
| int | SDL::WaitUntilStreamSocketDrained (StreamSocketRef sock, Sint32 timeout) |
| Block until all of a stream socket's pending data is sent. | |
| int | SDL::ReadFromStreamSocket (StreamSocketRef sock, void *buf, int buflen) |
| Receive bytes that a remote system sent to a stream socket. | |
| void | SDL::SimulateStreamPacketLoss (StreamSocketRef sock, int percent_loss) |
| Enable simulated stream socket failures. | |
| void | SDL::DestroyStreamSocket (StreamSocketRaw sock) |
| Dispose of a previously-created stream socket. | |
| DatagramSocket | SDL::CreateDatagramSocket (AddressRef addr, Uint16 port, PropertiesRef props) |
| Create and bind a new datagram socket. | |
| bool | SDL::SendDatagram (DatagramSocketRef sock, AddressRef address, Uint16 port, const void *buf, int buflen) |
| Send a new packet over a datagram socket to a remote system. | |
| bool | SDL::ReceiveDatagram (DatagramSocketRef sock, Datagram &dgram) |
| Receive a new packet that a remote system sent to a datagram socket. | |
| Datagram | SDL::ReceiveDatagram (DatagramSocketRef sock) |
| Receive a new packet that a remote system sent to a datagram socket. | |
| void | SDL::DestroyDatagram (DatagramRaw dgram) |
| Dispose of a datagram packet previously received. | |
| void | SDL::SimulateDatagramPacketLoss (DatagramSocketRef sock, int percent_loss) |
| Enable simulated datagram socket failures. | |
| void | SDL::DestroyDatagramSocket (DatagramSocketRaw sock) |
| Dispose of a previously-created datagram socket. | |
| int | SDL::WaitUntilInputAvailable (void **vsockets, int numsockets, Sint32 timeout) |
| Block on multiple sockets until at least one has data available. | |
| SDL::Address::Address (StringParam host) | |
| Resolve a human-readable hostname. | |
| SDL::Address::Address (const Address &address) | |
| Add a reference to an Address. | |
| Status | SDL::AddressBase::WaitUntilResolved (Sint32 timeout) |
| Block until an address is resolved. | |
| Status | SDL::AddressBase::GetStatus () |
| Check if an address is resolved, without blocking. | |
| const char * | SDL::AddressBase::GetString () |
| Get a human-readable string from a resolved address. | |
| const void * | SDL::AddressBase::GetBytes (int *num_bytes) |
| Get the protocol-level bytes of a network address from a resolved address. | |
| void | SDL::AddressBase::Unref () |
| Drop a reference to an Address. | |
| int | SDL::AddressBase::Compare (AddressRef b) const |
| Compare two Address objects. | |
| bool | SDL::AddressBase::operator== (const AddressBase &other) const |
| Compares two addresses for equality. | |
| auto | SDL::AddressBase::operator<=> (const AddressBase &other) const |
| Compares two addresses. | |
| StreamSocket | SDL::AddressBase::CreateClient (Uint16 port, PropertiesRef props) |
| Begin connecting a socket as a client to a remote server. | |
| SDL::StreamSocket::StreamSocket (AddressRef address, Uint16 port, PropertiesRef props) | |
| Begin connecting a socket as a client to a remote server. | |
| Status | SDL::StreamSocketBase::WaitUntilConnected (Sint32 timeout) |
| Block until a stream socket has connected to a server. | |
| Server | SDL::AddressBase::CreateServer (Uint16 port, PropertiesRef props) |
| Create a server, which listens for connections to accept. | |
| SDL::Server::Server (AddressRef addr, Uint16 port, PropertiesRef props) | |
| Create a server, which listens for connections to accept. | |
| void | SDL::ServerBase::AcceptClient (NET_StreamSocket **client_stream) |
| Create a stream socket for the next pending client connection. | |
| void | SDL::ServerBase::Destroy () |
| Dispose of a previously-created server. | |
| Address | SDL::StreamSocketBase::GetAddress () |
| Get the remote address of a stream socket. | |
| Status | SDL::StreamSocketBase::GetConnectionStatus () |
| Check if a stream socket is connected, without blocking. | |
| bool | SDL::StreamSocketBase::WriteTo (const void *buf, int buflen) |
| Send bytes over a stream socket to a remote system. | |
| int | SDL::StreamSocketBase::GetPendingWrites () |
| Query bytes still pending transmission on a stream socket. | |
| int | SDL::StreamSocketBase::WaitUntilDrained (Sint32 timeout) |
| Block until all of a stream socket's pending data is sent. | |
| int | SDL::StreamSocketBase::ReadFrom (void *buf, int buflen) |
| Receive bytes that a remote system sent to a stream socket. | |
| void | SDL::StreamSocketBase::SimulateStreamPacketLoss (int percent_loss) |
| Enable simulated stream socket failures. | |
| void | SDL::StreamSocketBase::Destroy () |
| Dispose of a previously-created stream socket. | |
| DatagramSocket | SDL::AddressBase::CreateDatagramSocket (Uint16 port, PropertiesRef props) |
| Create and bind a new datagram socket. | |
| SDL::DatagramSocket::DatagramSocket (AddressRef addr, Uint16 port, PropertiesRef props) | |
| Create and bind a new datagram socket. | |
| bool | SDL::DatagramSocketBase::SendDatagram (AddressRef address, Uint16 port, const void *buf, int buflen) |
| Send a new packet over a datagram socket to a remote system. | |
| bool | SDL::DatagramSocketBase::ReceiveDatagram (Datagram &dgram) |
| Receive a new packet that a remote system sent to a datagram socket. | |
| Datagram | SDL::DatagramSocketBase::ReceiveDatagram () |
| Receive a new packet that a remote system sent to a datagram socket. | |
| SDL::Datagram::Datagram (DatagramSocketRef sock) | |
| Receive a new packet that a remote system sent to a datagram socket. | |
| bool | SDL::DatagramBase::Receive (DatagramSocketRef sock) |
| Receive a new packet that a remote system sent to a datagram socket. | |
| void | SDL::DatagramBase::Destroy () |
| Dispose of a datagram packet previously received. | |
| void | SDL::DatagramSocketBase::SimulateDatagramPacketLoss (int percent_loss) |
| Enable simulated datagram socket failures. | |
| void | SDL::DatagramSocketBase::Destroy () |
| Dispose of a previously-created datagram socket. | |
Variables | |
| constexpr Status | SDL::FAILURE |
| Async operation complete, result was failure. | |
| constexpr Status | SDL::WAITING = NET_WAITING |
| Async operation is still in progress, check again later. | |
| constexpr Status | SDL::SUCCESS |
| Async operation complete, result was success. | |
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. Its 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:
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 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 Address to talk over the network. If you need to convert a hostname (such as "google.com" or "libsdl.org") into a Address, you can call ResolveHostname(), which will do the appropriate DNS queries on a background thread. Once these are ready, you can use the 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 Address you resolved with CreateClient(). Once the connection is established (a non-blocking operation), you'll have a StreamSocket object that can send and receive data over the connection, using WriteToStreamSocket() and ReadFromStreamSocket().
To instead be a server, that clients connect to, call CreateServer() to get a Server object. All a 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. CreateDatagramSocket() is used to prepare for datagram communication, then SendDatagram() and 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:
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:
| #define SDL_NET_MAJOR_VERSION |
The current major version of the SDL_net headers.
If this were SDL_net version 3.2.1, this value would be 3.
| #define SDL_NET_MICRO_VERSION |
The current micro (or patchlevel) version of the SDL_net headers.
If this were SDL_net version 3.2.1, this value would be 1.
| #define SDL_NET_MINOR_VERSION |
The current minor version of the SDL_net headers.
If this were SDL_net version 3.2.1, this value would be 2.
| #define SDL_NET_VERSION |
This is the version number macro for the current SDL_net version.
| #define SDL_NET_VERSION_ATLEAST | ( | X, | |
| Y, | |||
| Z ) |
This macro will evaluate to true if compiled with SDL_net at least X.Y.Z.
| using SDL::AddressRef = ResourceRefT<AddressBase> |
Reference for Address.
This does not take ownership!
| using SDL::DatagramRef = ResourceRefT<DatagramBase> |
Reference for Datagram.
This does not take ownership!
Reference for DatagramSocket.
This does not take ownership!
| using SDL::LocalAddressesArray = OwnArray<AddressRef, LocalAddressesArrayDeleter> |
Array of addresses returned by GetLocalAddresses.
The array is freed automatically when it goes out of scope.
| using SDL::ServerRef = ResourceRefT<ServerBase> |
Reference for Server.
This does not take ownership!
| using SDL::Status = NET_Status |
A tri-state for asynchronous operations.
Lots of tasks in SDL_net are asynchronous, as they can't complete until data passes over a network at some murky future point in time.
This includes sending data over a stream socket, resolving a hostname, connecting to a remote system, and other tasks.
The library never blocks on tasks that take time to complete, with the exception of functions named "Wait", which are intended to do nothing but block until a task completes. Functions that are attempting to do something that might block, or are querying the status of a task in-progress, will return a Status, so an app can see if a task completed, and its final outcome.
Reference for StreamSocket.
This does not take ownership!
|
inline |
Create a stream socket for the next pending client connection.
When a client connects to a server, their connection will be pending until the server accepts the connection. Once accepted, the server will be given a stream socket to communicate with the client, and they can send data to, and receive data from, each other.
Unlike CreateClient, stream sockets returned from this function are already connected and do not have to wait for the connection to complete, as server acceptance is the final step of connecting.
This function does not block. If there are no new connections pending, this function will return true (for success, but *client_stream will be set to nullptr. This is not an error and a common condition the app should expect. In fact, this function should be called in a loop until this condition occurs, so all pending connections are accepted in a single batch.
If you want the server to sleep until there's a new connection, you can use WaitUntilInputAvailable().
When done with the newly-accepted client, you can disconnect and dispose of the stream socket by calling DestroyStreamSocket().
| server | the server object to check for pending connections. |
| client_stream | Will be set to a new stream socket if a connection was pending, nullptr otherwise. |
| Error | on failure. |
|
inline |
Create a stream socket for the next pending client connection.
When a client connects to a server, their connection will be pending until the server accepts the connection. Once accepted, the server will be given a stream socket to communicate with the client, and they can send data to, and receive data from, each other.
Unlike CreateClient, stream sockets returned from this function are already connected and do not have to wait for the connection to complete, as server acceptance is the final step of connecting.
This function does not block. If there are no new connections pending, this function will return true (for success, but *client_stream will be set to nullptr. This is not an error and a common condition the app should expect. In fact, this function should be called in a loop until this condition occurs, so all pending connections are accepted in a single batch.
If you want the server to sleep until there's a new connection, you can use WaitUntilInputAvailable().
When done with the newly-accepted client, you can disconnect and dispose of the stream socket by calling DestroyStreamSocket().
| client_stream | Will be set to a new stream socket if a connection was pending, nullptr otherwise. |
| Error | on failure. |
|
inline |
Add a reference to an Address.
Since several pieces of the library might share a single Address, including a background thread that's working on resolving, these objects are referenced counted. This allows everything that's using it to declare they still want it, and drop their reference to the address when they are done with it. The object's resources are freed when the last reference is dropped.
This function adds a reference to an Address, increasing its reference count by one.
The documentation will tell you when the app has to explicitly unref an address. For example, ResolveHostname() creates addresses that are already referenced, so the caller needs to unref it when done.
Generally you only have to explicit ref an address when you have different parts of your own app that will be sharing an address. In normal usage, you only have to unref things you've created once (like you might free() something), but you are free to add extra refs if it makes sense.
This returns the same address passed as a parameter, which makes it easy to ref and assign in one step:
| address | The Address to add a reference to. |
|
inline |
Resolve a human-readable hostname.
SDL_net doesn't operate on human-readable hostnames (like www.libsdl.org but on computer-readable addresses. This function converts from one to the other. This process is known as "resolving" an address.
You can also use this to turn IP address strings (like "159.203.69.7") into Address objects.
Note that resolving an address is an asynchronous operation, since the library will need to ask a server on the internet to get the information it needs, and this can take time (and possibly fail later). This function will not block. It either returns nullptr (catastrophic failure) or an unresolved Address. Until the address resolves, it can't be used.
If you want to block until the resolution is finished, you can call WaitUntilResolved(). Otherwise, you can do a non-blocking check with GetAddressStatus().
When you are done with the returned Address, call UnrefAddress() to dispose of it. You need to do this even if resolution later fails asynchronously.
| host | The hostname to resolve. |
| Error | on failure. |
|
inline |
Compare two Address objects.
This compares two addresses, returning a value that is useful for qsort (or qsort).
| b | second address to compare. |
|
inline |
Compare two Address objects.
This compares two addresses, returning a value that is useful for qsort (or qsort).
| a | first address to compare. |
| b | second address to compare. |
|
inline |
Begin connecting a socket as a client to a remote server.
Each StreamSocket represents a single connection between systems. Usually, a client app will have one connection to a server app on a different computer, and the server app might have many connections from different clients. Each of these connections communicate over a separate stream socket.
Connecting is an asynchronous operation; this function does not block, and will return before the connection is complete. One has to then use WaitUntilConnected() or GetConnectionStatus() to see when the operation has completed, and if it was successful.
Once connected, you can read and write data to the returned socket. Stream sockets are a mode of reliable transmission, which means data will be received as a stream of bytes in the order you sent it. If there are problems in transmission, the system will deal with protocol negotiation and retransmission as necessary, transparent to your app, but this means until data is available in the order sent, the remote side will not get any new data. This is the tradeoff vs datagram sockets, where data can arrive in any order, or not arrive at all, without waiting, but the sender will not know.
Stream sockets don't employ any protocol (above the TCP level), so they can connect to servers that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
This function will fail if address is not finished resolving.
When you are done with this connection (whether it failed to connect or not), you must dispose of it with DestroyStreamSocket().
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
There are currently no extra properties for creating a client, so props should be zero. A future revision of SDL_net may add additional (optional) properties.
| port | the port on the remote server to connect to. |
| props | properties of the new client. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Begin connecting a socket as a client to a remote server.
Each StreamSocket represents a single connection between systems. Usually, a client app will have one connection to a server app on a different computer, and the server app might have many connections from different clients. Each of these connections communicate over a separate stream socket.
Connecting is an asynchronous operation; this function does not block, and will return before the connection is complete. One has to then use WaitUntilConnected() or GetConnectionStatus() to see when the operation has completed, and if it was successful.
Once connected, you can read and write data to the returned socket. Stream sockets are a mode of reliable transmission, which means data will be received as a stream of bytes in the order you sent it. If there are problems in transmission, the system will deal with protocol negotiation and retransmission as necessary, transparent to your app, but this means until data is available in the order sent, the remote side will not get any new data. This is the tradeoff vs datagram sockets, where data can arrive in any order, or not arrive at all, without waiting, but the sender will not know.
Stream sockets don't employ any protocol (above the TCP level), so they can connect to servers that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
This function will fail if address is not finished resolving.
When you are done with this connection (whether it failed to connect or not), you must dispose of it with DestroyStreamSocket().
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
There are currently no extra properties for creating a client, so props should be zero. A future revision of SDL_net may add additional (optional) properties.
| address | the address of the remote server to connect to. |
| port | the port on the remote server to connect to. |
| props | properties of the new client. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Create and bind a new datagram socket.
Datagram sockets follow different rules than stream sockets. They are not a reliable stream of bytes but rather packets, they are not limited to talking to a single other remote system, they do not maintain a single "connection" that can be dropped, and they are more nimble about network failures at the expense of being more complex to use. What makes sense for your app depends entirely on what your app is trying to accomplish.
Generally the idea of a datagram socket is that you send data one chunk ("packet") at a time to any address you want, and it arrives whenever it gets there, even if later packets get there first, and maybe it doesn't get there at all, and you don't know when anything of this happens by default.
This function creates a new datagram socket.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a socket or not. If this returns success, you can immediately start talking to the network.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
If you need to bind to a specific port (like a server), you should specify it in the port argument; datagram servers should do this, so they can be reached at a well-known port. If you only plan to initiate communications (like a client), you should specify 0 and let the system pick an unused port. Only one process can bind to a specific port at a time, so if you aren't acting as a server, you should choose 0. Datagram sockets can send individual packets to any port, so this just declares where data will arrive for your socket.
Datagram sockets don't employ any protocol (above the UDP level), so they can talk to apps that aren't using SDL_net, but if you want to speak any protocol beyond arbitrary packets of bytes, such as WebRTC, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| port | the port on the local address to listen for connections on, or zero for the system to decide. |
| props | properties of the new socket. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Create and bind a new datagram socket.
Datagram sockets follow different rules than stream sockets. They are not a reliable stream of bytes but rather packets, they are not limited to talking to a single other remote system, they do not maintain a single "connection" that can be dropped, and they are more nimble about network failures at the expense of being more complex to use. What makes sense for your app depends entirely on what your app is trying to accomplish.
Generally the idea of a datagram socket is that you send data one chunk ("packet") at a time to any address you want, and it arrives whenever it gets there, even if later packets get there first, and maybe it doesn't get there at all, and you don't know when anything of this happens by default.
This function creates a new datagram socket.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a socket or not. If this returns success, you can immediately start talking to the network.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
If you need to bind to a specific port (like a server), you should specify it in the port argument; datagram servers should do this, so they can be reached at a well-known port. If you only plan to initiate communications (like a client), you should specify 0 and let the system pick an unused port. Only one process can bind to a specific port at a time, so if you aren't acting as a server, you should choose 0. Datagram sockets can send individual packets to any port, so this just declares where data will arrive for your socket.
Datagram sockets don't employ any protocol (above the UDP level), so they can talk to apps that aren't using SDL_net, but if you want to speak any protocol beyond arbitrary packets of bytes, such as WebRTC, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| addr | the local address to listen for connections on, or nullptr to listen on all available local addresses. |
| port | the port on the local address to listen for connections on, or zero for the system to decide. |
| props | properties of the new socket. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Create a server, which listens for connections to accept.
An app that initiates connection to a remote computer is called a "client," and the thing the client connects to is called a "server."
Servers listen for and accept connections from clients, which spawns a new stream socket on the server's end, which it can then send/receive data on.
Use this function to create a server that will accept connections from other systems.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a server or not. If this returns success, you can immediately start accepting connections.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
After creating a server, you get stream sockets to talk to incoming client connections by calling AcceptClient().
Stream sockets don't employ any protocol (above the TCP level), so they can accept connections from clients that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| port | the port on the local address to listen for connections on. |
| props | properties of the new server. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Create a server, which listens for connections to accept.
An app that initiates connection to a remote computer is called a "client," and the thing the client connects to is called a "server."
Servers listen for and accept connections from clients, which spawns a new stream socket on the server's end, which it can then send/receive data on.
Use this function to create a server that will accept connections from other systems.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a server or not. If this returns success, you can immediately start accepting connections.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
After creating a server, you get stream sockets to talk to incoming client connections by calling AcceptClient().
Stream sockets don't employ any protocol (above the TCP level), so they can accept connections from clients that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| addr | the local address to listen for connections on, or nullptr. |
| port | the port on the local address to listen for connections on. |
| props | properties of the new server. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with DestroyDatagramSocket().
| sock | the datagram socket to send data through. |
|
inline |
Create and bind a new datagram socket.
Datagram sockets follow different rules than stream sockets. They are not a reliable stream of bytes but rather packets, they are not limited to talking to a single other remote system, they do not maintain a single "connection" that can be dropped, and they are more nimble about network failures at the expense of being more complex to use. What makes sense for your app depends entirely on what your app is trying to accomplish.
Generally the idea of a datagram socket is that you send data one chunk ("packet") at a time to any address you want, and it arrives whenever it gets there, even if later packets get there first, and maybe it doesn't get there at all, and you don't know when anything of this happens by default.
This function creates a new datagram socket.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a socket or not. If this returns success, you can immediately start talking to the network.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
If you need to bind to a specific port (like a server), you should specify it in the port argument; datagram servers should do this, so they can be reached at a well-known port. If you only plan to initiate communications (like a client), you should specify 0 and let the system pick an unused port. Only one process can bind to a specific port at a time, so if you aren't acting as a server, you should choose 0. Datagram sockets can send individual packets to any port, so this just declares where data will arrive for your socket.
Datagram sockets don't employ any protocol (above the UDP level), so they can talk to apps that aren't using SDL_net, but if you want to speak any protocol beyond arbitrary packets of bytes, such as WebRTC, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| addr | the local address to listen for connections on, or nullptr to listen on all available local addresses. |
| port | the port on the local address to listen for connections on, or zero for the system to decide. |
| props | properties of the new socket. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Dispose of a datagram packet previously received.
You must pass packets received through ReceiveDatagram to this function when you are done with them. This will free resources used by this packet and unref its Address.
If you want to save the sender's address from the packet past this time, it is safe to call RefAddress() on the address and hold onto its pointer, so long as you call UnrefAddress() on it when you are done with it.
Once you call this function, the datagram pointer becomes invalid and should not be used again by the app.
|
inline |
Dispose of a previously-created datagram socket.
This will abandon any data queued for sending that hasn't made it to the socket. If you need this data to arrive, you should wait for confirmation from the remote computer in some form that you devise yourself. Queued data is not guaranteed to arrive even if the library made efforts to transmit it here.
Any data that has arrived from the remote end of the connection that hasn't been read yet is lost.
|
inline |
Dispose of a previously-created server.
This will immediately disconnect any pending client connections that had not yet been accepted, but will not disconnect any existing accepted connections (which can still be used and must be destroyed separately). Further attempts to make new connections to this server will fail on the client side.
|
inline |
Dispose of a previously-created stream socket.
This will immediately disconnect the other side of the connection, if necessary. Further attempts to read or write the socket on the remote end will fail.
This will abandon any data queued for sending that hasn't made it to the socket. If you need this data to arrive, you should wait for it to transmit before destroying the socket with GetStreamSocketPendingWrites() or WaitUntilStreamSocketDrained(). Any data that has arrived from the remote end of the connection that hasn't been read yet is lost.
|
inline |
Dispose of a datagram packet previously received.
You must pass packets received through ReceiveDatagram to this function when you are done with them. This will free resources used by this packet and unref its Address.
If you want to save the sender's address from the packet past this time, it is safe to call RefAddress() on the address and hold onto its pointer, so long as you call UnrefAddress() on it when you are done with it.
Once you call this function, the datagram pointer becomes invalid and should not be used again by the app.
| dgram | the datagram packet to destroy. |
|
inline |
Dispose of a previously-created datagram socket.
This will abandon any data queued for sending that hasn't made it to the socket. If you need this data to arrive, you should wait for confirmation from the remote computer in some form that you devise yourself. Queued data is not guaranteed to arrive even if the library made efforts to transmit it here.
Any data that has arrived from the remote end of the connection that hasn't been read yet is lost.
| sock | datagram socket to destroy. |
|
inline |
Dispose of a previously-created server.
This will immediately disconnect any pending client connections that had not yet been accepted, but will not disconnect any existing accepted connections (which can still be used and must be destroyed separately). Further attempts to make new connections to this server will fail on the client side.
| server | server to destroy. |
|
inline |
Dispose of a previously-created stream socket.
This will immediately disconnect the other side of the connection, if necessary. Further attempts to read or write the socket on the remote end will fail.
This will abandon any data queued for sending that hasn't made it to the socket. If you need this data to arrive, you should wait for it to transmit before destroying the socket with GetStreamSocketPendingWrites() or WaitUntilStreamSocketDrained(). Any data that has arrived from the remote end of the connection that hasn't been read yet is lost.
| sock | stream socket to destroy. |
|
inline |
Free the results from GetLocalAddresses.
This will unref all addresses in the array and free the array itself.
Since addresses are reference counted, it is safe to keep any addresses you want from this array even after calling this function, as long as you called RefAddress() on them first.
It is safe to pass a nullptr in here, it will be ignored.
You most likely don't need to call this function directly, as the LocalAddressesArray type will call it for you when the array goes out of scope.
| addresses | A pointer returned by GetLocalAddresses(). |
|
inline |
Get the remote address of a stream socket.
This reports the address of the remote side of a stream socket, which might still be pending connnection.
This adds a reference to the address; the caller must call UnrefAddress() when done with it.
| Error | on failure. |
|
inline |
Get the protocol-level bytes of a network address from a resolved address.
This data is not human-readable, is protocol-specific, and might not even be in a specific byte order.
This is only useful for possibly hashing, to map a address to a specific player in a game, or possibly for handing to a system-level networking API (which is not recommended; an app does this at their own risk).
Do not store these bytes for future runs of the program; there is no promise the format won't change.
On return *num_bytes will hold the number of bytes provided with the address. Since the data is not nullptr-terminated, this is the only way to determine its size; as such, this parameter must not be nullptr.
Do not free or modify the returned data; it belongs to the Address that was queried, and is valid as long as the object lives. Either make sure the address has a reference as long as you need this or make a copy of the bytes.
This will return nullptr if resolution is still in progress, or if resolution failed. You can use GetAddressStatus() or WaitUntilResolved() to make sure resolution has successfully completed before calling this.
A human-readable version is available in GetAddressString() and isn't any less efficient to query than the raw bytes.
| address | The Address to query. |
| num_bytes | on return, will be set to the number of bytes returned. |
| Error | on failure. |
|
inline |
Check if an address is resolved, without blocking.
The Address objects returned by ResolveHostname take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
This function allows you to check the progress of that work without blocking.
Resolution can fail after some time (DNS server took awhile to reply that the hostname isn't recognized, etc), so be sure to check the result of this function instead of assuming it worked because it's non-zero!
Once an address is successfully resolved, it can be used to connect to the host represented by the address.
| address | The Address to query. |
|
inline |
Get a human-readable string from a resolved address.
This returns a string that's "human-readable", in that it's probably a string of numbers and symbols, like "159.203.69.7" or "2604:a880:800:a1::71f:3001". It won't be the original hostname (like "icculus.org"), but it's suitable for writing to a log file, etc.
Do not free or modify the returned string; it belongs to the Address that was queried, and is valid as long as the object lives. Either make sure the address has a reference as long as you need this or make a copy of the string.
This will return nullptr if resolution is still in progress, or if resolution failed. You can use GetAddressStatus() or WaitUntilResolved() to make sure resolution has successfully completed before calling this.
| address | The Address to query. |
| Error | on failure. |
|
inline |
Get the protocol-level bytes of a network address from a resolved address.
This data is not human-readable, is protocol-specific, and might not even be in a specific byte order.
This is only useful for possibly hashing, to map a address to a specific player in a game, or possibly for handing to a system-level networking API (which is not recommended; an app does this at their own risk).
Do not store these bytes for future runs of the program; there is no promise the format won't change.
On return *num_bytes will hold the number of bytes provided with the address. Since the data is not nullptr-terminated, this is the only way to determine its size; as such, this parameter must not be nullptr.
Do not free or modify the returned data; it belongs to the Address that was queried, and is valid as long as the object lives. Either make sure the address has a reference as long as you need this or make a copy of the bytes.
This will return nullptr if resolution is still in progress, or if resolution failed. You can use GetAddressStatus() or WaitUntilResolved() to make sure resolution has successfully completed before calling this.
A human-readable version is available in GetAddressString() and isn't any less efficient to query than the raw bytes.
| num_bytes | on return, will be set to the number of bytes returned. |
| Error | on failure. |
|
inline |
Check if a stream socket is connected, without blocking.
The StreamSocket objects returned by CreateClient take time to do negotiate a connection to a server, so it does so asynchronously instead of making your program wait an indefinite amount of time.
This function allows you to check the progress of that work without blocking.
Connection can fail after some time (server took a while to respond, and then rejected the connection), so be sure to check the result of this function instead of assuming it worked because it's non-zero!
Once a connection is successfully made, the stream socket can be used to send and receive data with the server.
Note that if the connection succeeds, but later the connection is dropped, this will still report the connection as successful, as it only deals with the initial asynchronous work of getting connected; you'll know the connection dropped later when your reads and writes report failures.
| sock | the stream socket to query. |
|
inline |
Check if a stream socket is connected, without blocking.
The StreamSocket objects returned by CreateClient take time to do negotiate a connection to a server, so it does so asynchronously instead of making your program wait an indefinite amount of time.
This function allows you to check the progress of that work without blocking.
Connection can fail after some time (server took a while to respond, and then rejected the connection), so be sure to check the result of this function instead of assuming it worked because it's non-zero!
Once a connection is successfully made, the stream socket can be used to send and receive data with the server.
Note that if the connection succeeds, but later the connection is dropped, this will still report the connection as successful, as it only deals with the initial asynchronous work of getting connected; you'll know the connection dropped later when your reads and writes report failures.
|
inline |
Obtain a list of local addresses on the system.
This returns addresses that you can theoretically bind a socket to, to accept connections from other machines at that address.
You almost never need this function; first, it's hard to tell what is a good address to bind to, without asking the user (who will likely find it equally hard to decide). Second, most machines will have lots of private addresses that are accessible on the same LAN, but not public ones that are accessible from the outside Internet.
Usually it's better to use CreateServer() or CreateDatagramSocket() with a nullptr address, to say "bind to all interfaces."
The array of addresses returned from this is guaranteed to be nullptr-terminated. You can also pass a pointer to an int, which will return the final count, not counting the nullptr at the end of the array.
| Error | on failure. |
|
inline |
Query bytes still pending transmission on a stream socket.
If WriteToStreamSocket() couldn't send all its data immediately, it will queue it to be sent later. This function lets the app see how much of that queue is still pending to be sent.
The library will try to send more queued data before reporting what's left, but it will not block to do so.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
|
inline |
Check if an address is resolved, without blocking.
The Address objects returned by ResolveHostname take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
This function allows you to check the progress of that work without blocking.
Resolution can fail after some time (DNS server took awhile to reply that the hostname isn't recognized, etc), so be sure to check the result of this function instead of assuming it worked because it's non-zero!
Once an address is successfully resolved, it can be used to connect to the host represented by the address.
|
inline |
Get the remote address of a stream socket.
This reports the address of the remote side of a stream socket, which might still be pending connnection.
This adds a reference to the address; the caller must call UnrefAddress() when done with it.
| sock | the stream socket to query. |
| Error | on failure. |
|
inline |
Query bytes still pending transmission on a stream socket.
If WriteToStreamSocket() couldn't send all its data immediately, it will queue it to be sent later. This function lets the app see how much of that queue is still pending to be sent.
The library will try to send more queued data before reporting what's left, but it will not block to do so.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| sock | the stream socket to query. |
|
inline |
Get a human-readable string from a resolved address.
This returns a string that's "human-readable", in that it's probably a string of numbers and symbols, like "159.203.69.7" or "2604:a880:800:a1::71f:3001". It won't be the original hostname (like "icculus.org"), but it's suitable for writing to a log file, etc.
Do not free or modify the returned string; it belongs to the Address that was queried, and is valid as long as the object lives. Either make sure the address has a reference as long as you need this or make a copy of the string.
This will return nullptr if resolution is still in progress, or if resolution failed. You can use GetAddressStatus() or WaitUntilResolved() to make sure resolution has successfully completed before calling this.
| Error | on failure. |
|
inline |
Compares two addresses.
Returns std::strong_ordering::less if this address is less than the other, std::strong_ordering::greater if this address is greater than the other, and std::strong_ordering::equal if they are equal.
|
inline |
Compares two addresses for equality.
Returns true if they are the same, false otherwise.
|
inline |
Receive bytes that a remote system sent to a stream socket.
Stream sockets are reliable, which means data sent over them will arrive in the order it was transmitted, and the system will retransmit data as necessary to ensure its delivery. Which is to say, short of catastrophic failure, data will arrive, possibly with severe delays. Also, "catastrophic failure" isn't an uncommon event.
(This is opposed to Datagram sockets, which send chunks of data that might arrive in any order, or not arrive at all, but you never wait for missing chunks to show up.)
Stream sockets are bidirectional; you can read and write from the same stream, and the other end of the connection can, too.
This function returns data that has arrived for the stream socket that hasn't been read yet. Data is provided in the order it was sent on the remote side. This function may return less data than requested, depending on what is available at the time, and also the app isn't required to read all available data at once.
This call never blocks; if no new data is available at the time of the call, it returns 0 immediately. The caller can try again later.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| buf | a pointer to a buffer where received data will be collected. |
| buflen | the size of the buffer pointed to by buf, in bytes. This is the maximum that will be read from the stream socket. |
|
inline |
Receive bytes that a remote system sent to a stream socket.
Stream sockets are reliable, which means data sent over them will arrive in the order it was transmitted, and the system will retransmit data as necessary to ensure its delivery. Which is to say, short of catastrophic failure, data will arrive, possibly with severe delays. Also, "catastrophic failure" isn't an uncommon event.
(This is opposed to Datagram sockets, which send chunks of data that might arrive in any order, or not arrive at all, but you never wait for missing chunks to show up.)
Stream sockets are bidirectional; you can read and write from the same stream, and the other end of the connection can, too.
This function returns data that has arrived for the stream socket that hasn't been read yet. Data is provided in the order it was sent on the remote side. This function may return less data than requested, depending on what is available at the time, and also the app isn't required to read all available data at once.
This call never blocks; if no new data is available at the time of the call, it returns 0 immediately. The caller can try again later.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| sock | the stream socket to receive data from. |
| buf | a pointer to a buffer where received data will be collected. |
| buflen | the size of the buffer pointed to by buf, in bytes. This is the maximum that will be read from the stream socket. |
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
| sock | the datagram socket to send data through. |
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
| dgram | a reference to the datagram packet object. |
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
| sock | the datagram socket to send data through. |
|
inline |
Receive a new packet that a remote system sent to a datagram socket.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, so you'll never receive half a packet.
This call never blocks; if no new data is available at the time of the call, it returns true immediately. The caller can try again later.
On a successful call to this function, it returns true, even if no new packets are available, so you should check for a successful return and a non-nullptr value in *dgram to decide if a new packet is available.
You must pass received packets to DestroyDatagram when you are done with them. If you want to save the sender's address past this time, it is safe to call RefAddress() on the address and hold onto the pointer, so long as you call UnrefAddress() on it when you are done with it.
Since datagrams can arrive from any address or port on the network without prior warning, this information is available in the Datagram object that is provided by this function, and this is the only way to know who to reply to. Even if you aren't acting as a "server," packets can still arrive at your socket if someone sends one.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
| sock | the datagram socket to send data through. |
| dgram | a pointer to the datagram packet pointer. |
|
inline |
Add a reference to an Address.
Since several pieces of the library might share a single Address, including a background thread that's working on resolving, these objects are referenced counted. This allows everything that's using it to declare they still want it, and drop their reference to the address when they are done with it. The object's resources are freed when the last reference is dropped.
This function adds a reference to an Address, increasing its reference count by one.
The documentation will tell you when the app has to explicitly unref an address. For example, ResolveHostname() creates addresses that are already referenced, so the caller needs to unref it when done.
Generally you only have to explicit ref an address when you have different parts of your own app that will be sharing an address. In normal usage, you only have to unref things you've created once (like you might free() something), but you are free to add extra refs if it makes sense.
This returns the same address passed as a parameter, which makes it easy to ref and assign in one step:
| address | The Address to add a reference to. |
|
inline |
Resolve a human-readable hostname.
SDL_net doesn't operate on human-readable hostnames (like www.libsdl.org but on computer-readable addresses. This function converts from one to the other. This process is known as "resolving" an address.
You can also use this to turn IP address strings (like "159.203.69.7") into Address objects.
Note that resolving an address is an asynchronous operation, since the library will need to ask a server on the internet to get the information it needs, and this can take time (and possibly fail later). This function will not block. It either returns nullptr (catastrophic failure) or an unresolved Address. Until the address resolves, it can't be used.
If you want to block until the resolution is finished, you can call WaitUntilResolved(). Otherwise, you can do a non-blocking check with GetAddressStatus().
When you are done with the returned Address, call UnrefAddress() to dispose of it. You need to do this even if resolution later fails asynchronously.
| host | The hostname to resolve. |
| Error | on failure. |
|
inline |
Send a new packet over a datagram socket to a remote system.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, as opposed to stream sockets, where individual bytes might trickle in as they attempt to reliably deliver a stream of data.
Datagram packets might arrive in a different order than you sent them, or they may just be lost while travelling across the network. You have to plan for this. As an added confusion, since SDL_net might send the same packet on multiple interfaces, you might get duplicate packets, possibly from different network addresses. You have to plan for this, too.
You can send to any address and port on the network, but there has to be a datagram socket waiting for the data on the other side for the packet not to be lost.
General wisdom is that you shouldn't send a packet larger than 1500 bytes over the Internet, as bad routers might fragment or lose larger ones, but this limit is not hardcoded into SDL_net and in good conditions you might be able to send significantly more.
This call never blocks; if it can't send the data immediately, the library will queue it for later transmission. There is no query to see what is still queued, as datagram transmission is unreliable, so you should never assume anything about queued data.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
Sending to a nullptr address is treated as a request to broadcast a packet. Note that this will report failure immediately if the socket was not created with broadcast permission. Broadcast packets are (more or less) sent to every machine on the LAN, unconditionally.
WARNING: It is possible to build a game where everyone is playing on the same LAN, and every player is simply broadcasting packets. This is absolutely the wrong thing to do, however. Broadcast packets go to every device on the LAN, whether they want them or not. The game DOOM, in its heyday, was capable of bringing entire networks to their knees , as many players on the same network would all be broadcasting relentlessly.
In practice, broadcasting sparingly can be useful for certain functionality: a LAN-only client broadcasting a few packets to ask for available servers, and running servers replying directly to that client without broadcasting at all, is reasonable and safe. Once clients and servers have found each other, they can communicate directly without any broadcasting at all. For peer-to-peer games, once connection is established, it's better to either send unique packets to each known player, or use a multicasting (which works like broadcast, but only routes packets to devices that are explicitly listening for it).
With IPv6, which doesn't support broadcasts, broadcasting is faked with multicast to the all-nodes link-local multicast group, ff02::1, either on a specific interface or letting the OS choose the default. Other protocols might fake broadcast operations in similar ways in the future.
| address | the Address object address. May be nullptr to broadcast. |
| port | the address port. |
| buf | a pointer to the data to send as a single packet. |
| buflen | the size of the data to send, in bytes. |
|
inline |
Send a new packet over a datagram socket to a remote system.
Datagram sockets send packets of data. They either arrive as complete packets or they don't arrive at all, as opposed to stream sockets, where individual bytes might trickle in as they attempt to reliably deliver a stream of data.
Datagram packets might arrive in a different order than you sent them, or they may just be lost while travelling across the network. You have to plan for this. As an added confusion, since SDL_net might send the same packet on multiple interfaces, you might get duplicate packets, possibly from different network addresses. You have to plan for this, too.
You can send to any address and port on the network, but there has to be a datagram socket waiting for the data on the other side for the packet not to be lost.
General wisdom is that you shouldn't send a packet larger than 1500 bytes over the Internet, as bad routers might fragment or lose larger ones, but this limit is not hardcoded into SDL_net and in good conditions you might be able to send significantly more.
This call never blocks; if it can't send the data immediately, the library will queue it for later transmission. There is no query to see what is still queued, as datagram transmission is unreliable, so you should never assume anything about queued data.
If there's a fatal error, this function will return false. Datagram sockets generally won't report failures, because there is no state like a "connection" to fail at this level, but may report failure for unrecoverable system-level conditions; once a datagram socket fails, you should assume it is no longer usable and should destroy it with SDL_DestroyDatagramSocket().
Sending to a nullptr address is treated as a request to broadcast a packet. Note that this will report failure immediately if the socket was not created with broadcast permission. Broadcast packets are (more or less) sent to every machine on the LAN, unconditionally.
WARNING: It is possible to build a game where everyone is playing on the same LAN, and every player is simply broadcasting packets. This is absolutely the wrong thing to do, however. Broadcast packets go to every device on the LAN, whether they want them or not. The game DOOM, in its heyday, was capable of bringing entire networks to their knees , as many players on the same network would all be broadcasting relentlessly.
In practice, broadcasting sparingly can be useful for certain functionality: a LAN-only client broadcasting a few packets to ask for available servers, and running servers replying directly to that client without broadcasting at all, is reasonable and safe. Once clients and servers have found each other, they can communicate directly without any broadcasting at all. For peer-to-peer games, once connection is established, it's better to either send unique packets to each known player, or use a multicasting (which works like broadcast, but only routes packets to devices that are explicitly listening for it).
With IPv6, which doesn't support broadcasts, broadcasting is faked with multicast to the all-nodes link-local multicast group, ff02::1, either on a specific interface or letting the OS choose the default. Other protocols might fake broadcast operations in similar ways in the future.
| sock | the datagram socket to send data through. |
| address | the Address object address. May be nullptr to broadcast. |
| port | the address port. |
| buf | a pointer to the data to send as a single packet. |
| buflen | the size of the data to send, in bytes. |
|
inline |
Create a server, which listens for connections to accept.
An app that initiates connection to a remote computer is called a "client," and the thing the client connects to is called a "server."
Servers listen for and accept connections from clients, which spawns a new stream socket on the server's end, which it can then send/receive data on.
Use this function to create a server that will accept connections from other systems.
This function does not block, and is not asynchronous, as the system can decide immediately if it can create a server or not. If this returns success, you can immediately start accepting connections.
You can specify an address to listen for connections on; this address must be local to the system, and probably one returned by GetLocalAddresses(), but almost always you just want to specify nullptr here, to listen on any address available to the app.
After creating a server, you get stream sockets to talk to incoming client connections by calling AcceptClient().
Stream sockets don't employ any protocol (above the TCP level), so they can accept connections from clients that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
The caller may supply properties to customize behavior. This is optional, and a value of zero for props will request defaults for all properties.
These are the supported properties:
| addr | the local address to listen for connections on, or nullptr. |
| port | the port on the local address to listen for connections on. |
| props | properties of the new server. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Enable simulated address resolution failures.
Often times, testing a networked app on your development machine–which might have a wired connection to a fast, reliable network service–won't expose bugs that happen when networks intermittently fail in the real world, when the wifi is flakey and firewalls get in the way.
This function allows you to tell the library to pretend that some percentage of address resolutions will fail.
The higher the percentage, the more resolutions will fail and/or take longer for resolution to complete.
Setting this to zero (the default) will disable the simulation. Setting to 100 means everything fails unconditionally. At what percent the system merely borders on unusable is left as an exercise to the app developer.
This is intended for debugging purposes, to simulate real-world conditions that are various degrees of terrible. You probably should not call this in production code, where you'll likely see real failures anyhow.
| percent_loss | A number between 0 and 100. Higher means more failures. Zero to disable. |
|
inline |
Enable simulated datagram socket failures.
Often times, testing a networked app on your development machine–which might have a wired connection to a fast, reliable network service–won't expose bugs that happen when networks intermittently fail in the real world, when the wifi is flakey and firewalls get in the way.
This function allows you to tell the library to pretend that some percentage of datagram socket data transmission will fail.
The library will randomly lose packets (both incoming and outgoing) at an average matching percent_loss. Setting this to zero (the default) will disable the simulation. Setting to 100 means everything fails unconditionally and no further data will get through. At what percent the system merely borders on unusable is left as an exercise to the app developer.
This is intended for debugging purposes, to simulate real-world conditions that are various degrees of terrible. You probably should not call this in production code, where you'll likely see real failures anyhow.
| percent_loss | A number between 0 and 100. Higher means more failures. Zero to disable. |
|
inline |
Enable simulated datagram socket failures.
Often times, testing a networked app on your development machine–which might have a wired connection to a fast, reliable network service–won't expose bugs that happen when networks intermittently fail in the real world, when the wifi is flakey and firewalls get in the way.
This function allows you to tell the library to pretend that some percentage of datagram socket data transmission will fail.
The library will randomly lose packets (both incoming and outgoing) at an average matching percent_loss. Setting this to zero (the default) will disable the simulation. Setting to 100 means everything fails unconditionally and no further data will get through. At what percent the system merely borders on unusable is left as an exercise to the app developer.
This is intended for debugging purposes, to simulate real-world conditions that are various degrees of terrible. You probably should not call this in production code, where you'll likely see real failures anyhow.
| sock | The socket to set a failure rate on. |
| percent_loss | A number between 0 and 100. Higher means more failures. Zero to disable. |
|
inline |
Enable simulated stream socket failures.
Often times, testing a networked app on your development machine–which might have a wired connection to a fast, reliable network service–won't expose bugs that happen when networks intermittently fail in the real world, when the wifi is flakey and firewalls get in the way.
This function allows you to tell the library to pretend that some percentage of stream socket data transmission will fail.
Since stream sockets are reliable, failure in this case pretends that packets are getting lost on the network, making the stream retransmit to deal with it. To simulate this, the library will introduce some amount of delay before it sends or receives data on the socket. The higher the percentage, the more delay is introduced for bytes to make their way to their final destination. The library may also decide to drop connections at random, to simulate disasterous network conditions.
Setting this to zero (the default) will disable the simulation. Setting to 100 means everything fails unconditionally and no further data will get through (and perhaps your sockets eventually fail). At what percent the system merely borders on unusable is left as an exercise to the app developer.
This is intended for debugging purposes, to simulate real-world conditions that are various degrees of terrible. You probably should not call this in production code, where you'll likely see real failures anyhow.
| sock | The socket to set a failure rate on. |
| percent_loss | A number between 0 and 100. Higher means more failures. Zero to disable. |
|
inline |
Enable simulated stream socket failures.
Often times, testing a networked app on your development machine–which might have a wired connection to a fast, reliable network service–won't expose bugs that happen when networks intermittently fail in the real world, when the wifi is flakey and firewalls get in the way.
This function allows you to tell the library to pretend that some percentage of stream socket data transmission will fail.
Since stream sockets are reliable, failure in this case pretends that packets are getting lost on the network, making the stream retransmit to deal with it. To simulate this, the library will introduce some amount of delay before it sends or receives data on the socket. The higher the percentage, the more delay is introduced for bytes to make their way to their final destination. The library may also decide to drop connections at random, to simulate disasterous network conditions.
Setting this to zero (the default) will disable the simulation. Setting to 100 means everything fails unconditionally and no further data will get through (and perhaps your sockets eventually fail). At what percent the system merely borders on unusable is left as an exercise to the app developer.
This is intended for debugging purposes, to simulate real-world conditions that are various degrees of terrible. You probably should not call this in production code, where you'll likely see real failures anyhow.
| percent_loss | A number between 0 and 100. Higher means more failures. Zero to disable. |
|
inline |
Begin connecting a socket as a client to a remote server.
Each StreamSocket represents a single connection between systems. Usually, a client app will have one connection to a server app on a different computer, and the server app might have many connections from different clients. Each of these connections communicate over a separate stream socket.
Connecting is an asynchronous operation; this function does not block, and will return before the connection is complete. One has to then use WaitUntilConnected() or GetConnectionStatus() to see when the operation has completed, and if it was successful.
Once connected, you can read and write data to the returned socket. Stream sockets are a mode of reliable transmission, which means data will be received as a stream of bytes in the order you sent it. If there are problems in transmission, the system will deal with protocol negotiation and retransmission as necessary, transparent to your app, but this means until data is available in the order sent, the remote side will not get any new data. This is the tradeoff vs datagram sockets, where data can arrive in any order, or not arrive at all, without waiting, but the sender will not know.
Stream sockets don't employ any protocol (above the TCP level), so they can connect to servers that aren't using SDL_net, but if you want to speak any protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to implement that yourself on top of the stream socket.
This function will fail if address is not finished resolving.
When you are done with this connection (whether it failed to connect or not), you must dispose of it with DestroyStreamSocket().
Unlike BSD sockets or WinSock, you specify the port as a normal integer; you do not have to byteswap it into "network order," as the library will handle that for you.
There are currently no extra properties for creating a client, so props should be zero. A future revision of SDL_net may add additional (optional) properties.
| address | the address of the remote server to connect to. |
| port | the port on the remote server to connect to. |
| props | properties of the new client. Specify zero for defaults. |
| Error | on failure. |
|
inline |
Drop a reference to an Address.
Since several pieces of the library might share a single Address, including a background thread that's working on resolving, these objects are referenced counted. This allows everything that's using it to declare they still want it, and drop their reference to the address when they are done with it. The object's resources are freed when the last reference is dropped.
This function drops a reference to an Address, decreasing its reference count by one.
The documentation will tell you when the app has to explicitly unref an address. For example, ResolveHostname() creates addresses that are already referenced, so the caller needs to unref it when done.
|
inline |
Drop a reference to an Address.
Since several pieces of the library might share a single Address, including a background thread that's working on resolving, these objects are referenced counted. This allows everything that's using it to declare they still want it, and drop their reference to the address when they are done with it. The object's resources are freed when the last reference is dropped.
This function drops a reference to an Address, decreasing its reference count by one.
The documentation will tell you when the app has to explicitly unref an address. For example, ResolveHostname() creates addresses that are already referenced, so the caller needs to unref it when done.
| address | The Address to drop a reference to. |
Block until a stream socket has connected to a server.
The StreamSocket objects returned by CreateClient take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
However, if you want your program to sleep until the connection is complete, you can call this function.
This function takes a timeout value, represented in milliseconds, of how long to wait for resolution to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetConnectionStatus).
Connections can fail after some time (server took awhile to respond at all, and then refused the connection outright), so be sure to check the result of this function instead of assuming it worked!
Once a connection is successfully made, the socket may read data from, or write data to, the connected server.
If you don't want your program to block, you can call GetConnectionStatus() from time to time until you get a non-zero result.
| timeout | Number of milliseconds to wait for resolution to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Block until a stream socket has connected to a server.
The StreamSocket objects returned by CreateClient take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
However, if you want your program to sleep until the connection is complete, you can call this function.
This function takes a timeout value, represented in milliseconds, of how long to wait for resolution to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetConnectionStatus).
Connections can fail after some time (server took awhile to respond at all, and then refused the connection outright), so be sure to check the result of this function instead of assuming it worked!
Once a connection is successfully made, the socket may read data from, or write data to, the connected server.
If you don't want your program to block, you can call GetConnectionStatus() from time to time until you get a non-zero result.
| sock | The StreamSocket object to wait on. |
| timeout | Number of milliseconds to wait for resolution to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Block until all of a stream socket's pending data is sent.
If WriteToStreamSocket() couldn't send all its data immediately, it will queue it to be sent later. This function lets the app sleep until all the data is transmitted.
This function takes a timeout value, represented in milliseconds, of how long to wait for transmission to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetStreamSocketPendingWrites).
If you don't want your program to block, you can call GetStreamSocketPendingWrites from time to time until you get a result <= 0.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| timeout | Number of milliseconds to wait for draining to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Block on multiple sockets until at least one has data available.
This is a complex function that most apps won't need, but it could be used to implement a more efficient server or i/o thread in some cases.
This allows you to give it a list of objects and wait for new input to become available on any of them. The calling thread is put to sleep until such a time.
The following things can be specified in the vsockets array, cast to void *:
This function takes a timeout value, represented in milliseconds, of how long to wait for resolution to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately.
This returns the number of items that have new input, but it does not tell you which ones; since access to them is non-blocking, you can just try to read from each of them and see which are ready. If nothing is ready and the timeout is reached, this returns zero. On error, this returns -1.
| vsockets | an array of pointers to various objects that can be waited on, each cast to a void pointer. |
| numsockets | the number of pointers in the vsockets array. |
| timeout | Number of milliseconds to wait for new input to become available. -1 to wait indefinitely, 0 to check once without waiting. |
Block until an address is resolved.
The Address objects returned by ResolveHostname take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
However, if you want your program to sleep until the address resolution is complete, you can call this function.
This function takes a timeout value, represented in milliseconds, of how long to wait for resolution to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetAddressStatus).
Resolution can fail after some time (DNS server took awhile to reply that the hostname isn't recognized, etc), so be sure to check the result of this function instead of assuming it worked!
Once an address is successfully resolved, it can be used to connect to the host represented by the address.
If you don't want your program to block, you can call GetAddressStatus from time to time until you get a non-zero result.
| timeout | Number of milliseconds to wait for resolution to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Block until an address is resolved.
The Address objects returned by ResolveHostname take time to do their work, so it does so asynchronously instead of making your program wait an indefinite amount of time.
However, if you want your program to sleep until the address resolution is complete, you can call this function.
This function takes a timeout value, represented in milliseconds, of how long to wait for resolution to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetAddressStatus).
Resolution can fail after some time (DNS server took awhile to reply that the hostname isn't recognized, etc), so be sure to check the result of this function instead of assuming it worked!
Once an address is successfully resolved, it can be used to connect to the host represented by the address.
If you don't want your program to block, you can call GetAddressStatus from time to time until you get a non-zero result.
| address | The Address object to wait on. |
| timeout | Number of milliseconds to wait for resolution to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Block until all of a stream socket's pending data is sent.
If WriteToStreamSocket() couldn't send all its data immediately, it will queue it to be sent later. This function lets the app sleep until all the data is transmitted.
This function takes a timeout value, represented in milliseconds, of how long to wait for transmission to complete. Specifying a timeout of -1 instructs the library to wait indefinitely, and a timeout of 0 just checks the current status and returns immediately (and is functionally equivalent to calling GetStreamSocketPendingWrites).
If you don't want your program to block, you can call GetStreamSocketPendingWrites from time to time until you get a result <= 0.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning -1. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| sock | the stream socket to wait on. |
| timeout | Number of milliseconds to wait for draining to complete. -1 to wait indefinitely, 0 to check once without waiting. |
|
inline |
Send bytes over a stream socket to a remote system.
Stream sockets are reliable, which means data sent over them will arrive in the order it was transmitted, and the system will retransmit data as necessary to ensure its delivery. Which is to say, short of catastrophic failure, data will arrive, possibly with severe delays. Also, "catastrophic failure" isn't an uncommon event.
(This is opposed to Datagram sockets, which send chunks of data that might arrive in any order, or not arrive at all, but you never wait for missing chunks to show up.)
Stream sockets are bidirectional; you can read and write from the same stream, and the other end of the connection can, too.
This call never blocks; if it can't send the data immediately, the library will queue it for later transmission. You can use GetStreamSocketPendingWrites() to see how much is still queued for later transmission, or WaitUntilStreamSocketDrained() to block until all pending data has been sent.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning false. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| buf | a pointer to the data to send. |
| buflen | the size of the data to send, in bytes. |
|
inline |
Send bytes over a stream socket to a remote system.
Stream sockets are reliable, which means data sent over them will arrive in the order it was transmitted, and the system will retransmit data as necessary to ensure its delivery. Which is to say, short of catastrophic failure, data will arrive, possibly with severe delays. Also, "catastrophic failure" isn't an uncommon event.
(This is opposed to Datagram sockets, which send chunks of data that might arrive in any order, or not arrive at all, but you never wait for missing chunks to show up.)
Stream sockets are bidirectional; you can read and write from the same stream, and the other end of the connection can, too.
This call never blocks; if it can't send the data immediately, the library will queue it for later transmission. You can use GetStreamSocketPendingWrites() to see how much is still queued for later transmission, or WaitUntilStreamSocketDrained() to block until all pending data has been sent.
If the connection has failed (remote side dropped us, or one of a million other networking failures occurred), this function will report failure by returning false. Stream sockets only report failure for unrecoverable conditions; once a stream socket fails, you should assume it is no longer usable and should destroy it with DestroyStreamSocket().
| sock | the stream socket to send data through. |
| buf | a pointer to the data to send. |
| buflen | the size of the data to send, in bytes. |
|
constexpr |
Async operation complete, result was failure.
|
constexpr |
Async operation complete, result was success.