Socket attributes affect the way sockets operate. ioctlsocket() is the main WinSock function used to set and get socket attributes. This function accepts any one of three commands –
FIONBIO, FIONREAD, and
SIOCATMARK.
- SO_ACCEPTCONN
This option can only be used with getsockopt()
and it indicated whether a stream socket is listening. This option is not relevant with datagram sockets.
Applications rarely need to use this option since they know that a socket is listening if listen() succeeds.
- SO_BROADCAST
This option enables/disables the ability to send/receive datagrams addressed to the broadcast address (a call that references a stream socket will fail). You must call
setsockopt() with SO_BROADCAST before any attempt to send/receive broadcast datagrams.
What is a broadcast address? There are a number of answers. Here are all the relevant broadcast addresses to the TCP/IP address family:
Network-layer broadcast addresses:
- Limited IP broadcast (255.255.255.255)
Limited because the router will never forward them beyond the local
(sub) network.
- Net-directed IP broadcas
An IP address comprised of a standard network address portion and host portion with all bits set. For example, for class B network (128.127), the net-directed
IP address is 128.127.255.255. Routers optionally forward these.
- Subnet-directed IP broadcast
An IP address comprised of a subnet address portion and host portion with all bits set. All routers forward these.
- IP multicast
A class D IP address (range 224.0.0.0 to 239.255.255.255).
Link-layer broadcast addresses:
- hardware broadcast
Media-specific, ‘all-stations’ address.
- multicast
Media-specific hardware-settable address.
You need to use broadcast addresses with caution. Every network interface card will pick up every packets it sees that has a broadcast destination address. As long as you use broadcast addresses sparingly, there are two valid uses for them:
- Elicit responses from hosts bound to the target port number (heartbeat?)
- Update information to all hosts bound to the target port number.
For example you can send a probe to check for hosts running a particular datagram application, or you can periodically send information to a broadcast address to simultaneously update all datagram applications. Keep in mind that many routers do not forward broadcast
messages.
- SO_DONTLINGER
This option enables/disables immediate return from closesocket() function:
- Enabling SO_DONTLINGER
(default)
closesocket() returns immediately whether socket is blocking or non-blocking. Queued data will be sent, and the TCP/IP stack will attempt a graceful exit.
Closure occurs in the background.
- Disabling SO_DONTLINGER
Causes a blocking socket to block on closesocket()
until it completes (successful or not). Queued data will be sent, and the TCP/IP stack will attempt a graceful exit. Closure occurs in the foreground.
This option also causes a non-blocking socket to return immediately from closesocket()
with WSAEWOULDBLOCK error.
Disabling this option implicitly enables SO_LINGER with an indeterminate timeout value. Therefore, if you disable this option, explicitly enable
SO_LINGER with an explicit timeout value.
It is recommended not to use this option.
- SO_DONTROUTE
Purpose: This option is designed for multi-homed machines (i.e., they have more than one interface card). This option reroutes packets internally before they leave the local host machine so that they use the interface card most local to the destination host. It has the effect of reducing some misguided network traffic and may allow to use an under-used interface card to spread the work.
- SO_KEEPALIVE
Purpose: Enables/disables the keep-alive mechanisms on a stream socket. Keep-alives detect a virtual circuit failure on an idle connection and report an error to the application
With Keep-alive enabled, the TCP/IP stack periodically sends an acknowledgment request called a keep-alive. A keep-alive TCP segment does not contain any data. When a TCP/IP stack receives a keep-alive, it simply acknowledges it. If a sender does not receive an acknowledgment, it will attempt to retransmit a keep-alive. If none of the retransmissions receive an acknowledgment then the sender will reset the connection. Subsequently, any functions that reference that socket will fail with
WSAECONNABORTED.
Note: Enabling keep-alives on one side of a connection does not enable it on the other side; While the other side will acknowledge keep-alives, it will not send any keep-alives of its own.
WinSock does not provide an API to check for or change the keep-alive timeout value (it’s around 2 minutes)
Rather than use SO_KEEPALIVE, you should implement the keep-alive manually. It’s can be simply implemented using a timer to send data periodically, and the recipient can respond when it recognizes a keep-alive. In addition to having full control of the transmission period, by sending data you can benefit from the TCP retransmit logic, timeouts, and error reporting.
- SO_LINGER
Purpose: Enables/disabled immediate return from the closesocket()
option. This option is disabled by default, and closesocket()
returns immediately (for blocking and non-blocking sockets). This option is only valid on stream sockets and it basically determines whether the underlying TCP/IP stack will close a virtual circuit gracefully or forcefully by aborting the connection.
This option has three settings:
- Disabled (default)
closesocket() attempts a graceful close until default timeout expires, then does a forceful close. The close operation happened in the background since
closesocket() returns immediately in the default mode.
- Enabled with non-zero timeout
Attempts a graceful close until given timeout expires, then does a forceful close.
- Enabled with zero timeout
Initiates a forceful close and returns immediately whether socket is in blocking or non-blocking mode.
When a TCP/IP stack completes a graceful close:
- Sends all pending data from the system buffers.
- Waits for an acknowledgments of all data sent.
- Closes the circuit with a three-way handshake (send TCP <FIN>, receive <ACK><FIN>, then send <ACK>)
To avoid any errors when closing sockets, the recommended procedure to close a socket is:
- Call shutdown() with
how=1.
- Call recv() until it returns zero or fails with an error.
- Call closesocket().
It is recommended that you leave the default of SO_DONELINGER enabled for most TCP
applications.
- SO_OOBINLINE
Enables/disables receipt of urgent data within the normal stream. By default, urgent data arrives out-of-band
When this option is disabled (default), an application detects the arrival of out-of-band data with
FD_OOB event (or fd_set). The application then reads data by calling
recv() or recvfrom()
with the MSG_OOB flag set.
When this option is enabled, the application must scan each byte in the stream with
ioctlsocket() to detect OOB data.
- SO_RCVBUF & SO_SNDBUF
Used to set the size of the buffer that the underlying TCP/IP stack uses for receiving and sending data.
These options can be very useful for datagram or stream applications that deal with bulk-data. You can effectively increase the data through-put with these options.
- TCP_NODELAY
Disables/enables the Nagle algorithm. When this option is enabled the Nagle algorithm is disabled. Always have this option enabled.
Nagle Algorithm: This algorithm is a simple solution for optimizing network traffic. It decreases network traffic without decreasing throughput.
The algorithm stipulates that TCP segments should not be sent until:
- All outstanding data is acknowledged. Or,
- There is a maximum segment size (MSS) packet to send.