Socket Configuration Options: |
Socket options:
One can "get" (read) the current socket options or "set" them to new values. The default values are obtained from the OS:
Level | Option | Type | Default | Description |
---|
IPPROTO_IP | TCP_NODELAY | int | 0 | Don't delay send to coalesce packets. If set, disable the Nagle algorithm. When not set, data is buffered until there is a sufficient amount to send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network. Don't use with TCP_CORK. This option is overridden by TCP_CORK |
IPPROTO_IP | TCP_MAXSEG | int | 536 | Maximum segment size for outgoing TCP packets. TCP will impose its minimum and maximum bounds over the value provided. |
IPPROTO_IP | TCP_CORK | int | 0 | Control sending of partial frames. If set, don't send out partial frames. Not cross platform. |
IPPROTO_IP | TCP_KEEPIDLE | int | 7200 | When the SO_KEEPALIVE option is enabled, TCP probes a connection that has been idle for some amount of time. The default value for this idle period is 2 hours. The TCP_KEEPIDLE option can be used to affect this value for a given socket, and specifies the number of seconds of idle time between keepalive probes.
Not cross platform. This option takes an int value, with a range of 1 to 32767. |
IPPROTO_IP | TCP_KEEPINTVL | int | 75 | Specifies the interval between packets that are sent to validate the connection.
Not cross platform. |
IPPROTO_IP | TCP_KEEPCNT | int | 9 | When the SO_KEEPALIVE option is enabled, TCP probes a connection that has been idle for some amount of time. If the remote system does not respond to a keepalive probe, TCP retransmits the probe a certain number of times before a connection is considered to be broken. The TCP_KEEPCNT option can be used to affect this value for a given socket, and specifies the maximum number of keepalive probes to be sent. This option takes an int value, with a range of 1 to 32767. Not cross platform. |
IPPROTO_IP | TCP_SYNCNT | int | 5 | Number of SYN retransmits that TCP should send before aborting the attempt to connect. It cannot exceed 255. |
IPPROTO_IP | TCP_LINGER2 | int | 60 | Life time of orphaned FIN-WAIT-2 state. Not to be confused with option SO_LINGER
Not cross platform. |
SOL_SOCKET | SO_REUSEADDR | int
(bool) | 0 | Allow local address reuse. If a problem is encountered when attempting to bind to a port which has been closed but not released (may take up to 2 minutes as defined by TIME_WAIT). Apply the SO_REUSEADDR socket option to release the resource immediately and to get around the TIME_WAIT state.
0 = disables, 1 = enables |
SOL_SOCKET | SO_REUSEPORT | int
(bool) | 0 | This option is AF_INET socket-specific. This option allows multiple processes to share a port. All incoming multicast or broadcast UDP datagrams that are destined for the port are delivered to all sockets that are bound to the port. All processes that share the port must specify this option.
0 = disables, 1 = enables |
SOL_SOCKET | SO_ERROR | int
(bool) | 0 | When an error occurs on a socket, set error variable so_error and notify process
0 = disables, 1 = enables |
SOL_SOCKET | SO_BROADCAST | int
(bool) | 0 | Permit sending of broadcast datagrams
0 = disables, 1 = enables |
SOL_SOCKET | SO_SNDBUF | int
(value) | 16384 | Send buffer size |
SOL_SOCKET | SO_RCVBUF | int
(value) | 87380 | Receive buffer size |
SOL_SOCKET | SO_KEEPALIVE | int
(bool) | 0 | Periodically test if connection is alive
0 = disables, 1 = enables |
SOL_SOCKET | SO_SNDTIMEO | timeval
(struct) | 0
0 | Set timeout period for socket send.
Disable by setting timeval.tv_sec = 0 sec, timeval.tv_usec = 0 usec (default)
Affects write() writev() send() sendto() and sendmsg() |
SOL_SOCKET | SO_RCVTIMEO | timeval
(struct) | 0
0 | Set timeout period for socket receive.
Disable by setting timeval.tv_sec = 0 sec, timeval.tv_usec = 0 usec (default)
Affects read() readv() recv() recvfrom() and recvmsg() |
SOL_SOCKET | SO_LINGER | linger
(struct) | 0
0 | Specifies how close function will operate for connection protocols (TCP)
l_onoff: 0 = disables, 1 = enables
l_linger: 0 = unsent data discarded, 1 = close() does not return untill all unsent data is transmitted or remote connection is closed
Structure defined in sys/socket.h |
SOL_SOCKET | SO_RCVLOWAT | int
(value) | 1 | Specifies number of bytes used as a threshold by select() to consider a socket read ready |
SOL_SOCKET | SO_SNDLOWAT | int
(value) | 1 | Specifies number of bytes used as a threshold by select() to consider a socket write ready |
SOL_SOCKET | SO_TYPE | int
(value) | undefined | Specifies socket type (e.g., tcp (SOCK_STREAM), udp (SOCK_DGRAM), etc.)
For use with getsockopt() only. |
IPPROTO_IP macro defines are found in /usr/include/netinet/tcp.h
SOL_SOCKET macro defines require /usr/include/sys/socket.h
For a full list of options see the
TCP man pageFor a full list of IP options see the
IP(7) man pageFunction Prototypes:
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
getsockopt/setsockopt arguments:
int sockfd: Socket file descriptor. Returned by call to "socket".
int level: See table above
int optname: See table above
void *optval: Pointer to value or data structure
optlen: Length of "optval"
Returns 0: Sucess, -1: Failure and errno may be set.
Code to read socket options:
File: printSocketOptions.c
01 | #include
<sys/socket.h> |
02 | #include
<netinet/in.h> |
03 | #include
<netinet/tcp.h> |
13 | if ((socketHandle
= socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) |
19 | int iSocketOption
= 0; |
20 | int iSocketOptionLen
= sizeof ( int );; |
22 | struct linger
SocketOptionLinger; |
23 | int iSocketOptionLingerLen
= sizeof ( struct linger);; |
25 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_NODELAY, ( char *)&iSocketOption,
&iSocketOptionLen); |
26 | printf ( "Socket
TCP_NODELAY = %d\n" ,
iSocketOption); |
28 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_MAXSEG, ( char *)&iSocketOption,
&iSocketOptionLen); |
29 | printf ( "Socket
TCP_MAXSEG = %d\n" ,
iSocketOption); |
31 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_CORK, ( char *)&iSocketOption,
&iSocketOptionLen); |
32 | printf ( "Socket
TCP_CORK = %d\n" ,
iSocketOption); |
34 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_KEEPIDLE, ( char *)&iSocketOption,
&iSocketOptionLen); |
35 | printf ( "Socket
TCP_KEEPIDLE = %d\n" ,
iSocketOption); |
37 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_KEEPINTVL, ( char *)&iSocketOption,
&iSocketOptionLen); |
38 | printf ( "Socket
TCP_KEEPINTVL = %d\n" ,
iSocketOption); |
40 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_KEEPCNT, ( char *)&iSocketOption,
&iSocketOptionLen); |
41 | printf ( "Socket
TCP_KEEPCNT = %d\n" ,
iSocketOption); |
43 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_SYNCNT, ( char *)&iSocketOption,
&iSocketOptionLen); |
44 | printf ( "Socket
TCP_SYNCNT = %d\n" ,
iSocketOption); |
46 | getsockopt(socketHandle,
IPPROTO_TCP, TCP_LINGER2, ( char *)&iSocketOption,
&iSocketOptionLen); |
47 | printf ( "Socket
TCP_LINGER2 = %d\n" ,
iSocketOption); |
49 | getsockopt(socketHandle,
SOL_SOCKET, SO_REUSEADDR, ( char *)&iSocketOption,
&iSocketOptionLen); |
50 | printf ( "Socket
SO_REUSEADDR = %d\n" ,
iSocketOption); |
52 | getsockopt(socketHandle,
SOL_SOCKET, SO_ERROR, ( char *)&iSocketOption,
&iSocketOptionLen); |
53 | printf ( "Socket
SO_ERROR = %d\n" ,
iSocketOption); |
55 | getsockopt(socketHandle,
SOL_SOCKET, SO_BROADCAST, ( char *)&iSocketOption,
&iSocketOptionLen); |
56 | printf ( "Socket
SO_BROADCAST = %d\n" ,
iSocketOption); |
58 | getsockopt(socketHandle,
SOL_SOCKET, SO_KEEPALIVE, ( char *)&iSocketOption,
&iSocketOptionLen); |
59 | printf ( "Socket
SO_KEEPALIVE = %d\n" ,
iSocketOption); |
61 | getsockopt(socketHandle,
SOL_SOCKET, SO_SNDBUF, ( char *)&iSocketOption,
&iSocketOptionLen); |
62 | printf ( "Socket
SO_SNDBUF = %d\n" ,
iSocketOption); |
64 | getsockopt(socketHandle,
SOL_SOCKET, SO_RCVBUF, ( char *)&iSocketOption,
&iSocketOptionLen); |
65 | printf ( "Socket
SO_RCVBUF = %d\n" ,
iSocketOption); |
67 | getsockopt(socketHandle,
SOL_SOCKET, SO_LINGER, ( char *)&SocketOptionLinger,
&iSocketOptionLingerLen); |
68 | printf ( "Socket
SO_LINGER = %d time = %d\n" ,
SocketOptionLinger.l_onoff, SocketOptionLinger.l_linger); |
70 | getsockopt(socketHandle,
SOL_SOCKET, SO_RCVLOWAT, ( char *)&iSocketOption,
&iSocketOptionLen); |
71 | printf ( "Socket
SO_RCVLOWAT = %d\n" ,
iSocketOption); |
|
Compile: gcc -o printSocketOptions printSocketOptions.c
getsockopt man page: get a particular socket option for the specified socket.
Set socket options:
Socket "keep-alive":
1 | int iOption
= 1; //
Turn on keep-alive, 0 = disables, 1 = enables |
3 | if (setsockopt(socketHandle,
SOL_SOCKET, SO_KEEPALIVE, ( const char *)
&iOption, sizeof ( int ))
== SOCKET_ERROR) |
5 | cerr
<< "Set
keepalive: Keepalive option failed" <<
endl; |
|
Set socket client options:
Socket re-use:
1 | int iOption
= 0; //
Reuse address option to set, 0 = disables, 1 = enables |
3 | if (setsockopt(socketHandle,
SOL_SOCKET, SO_REUSEADDR, ( const char *)
&iOption, sizeof ( int ))
== SOCKET_ERROR) |
5 | cerr
<< "Set
reuse address: Client set reuse address option failed" <<
endl; |
|
When a socket connection is closed with a call to close(), shutdown() or exit(), both the client and server will send a FIN (final) packet and will then send an acknowledgment (ACK) that they received the packet. The side which initiates the
closure will be in a TIME_WAIT state until the process has been completed. This time out period is generally 2-4 minutes in duration. It is hoped that all packets are received in a timely manner and the entire time out duration is not required. When
an application is abnormally terminated, the TIME_WAIT period is entered for the full duration.
Setting the SO_REUSEADDR option explicitly allows a process to bind a port in the TIME_WAIT state. This is to avoid the error "bind: Address Already in Use". One caviat is that the process can not be to the same address and port
as the previous connection. If it is, the SO_REUSEADDR option will not help and the duration of the TIME_WAIT will be in effect.
For more info see
How to avoid the "Address Already in Use" error.
Solution: Enable socket linger:
5 | if (setsockopt(socketHandle,
SOL_SOCKET, SO_LINGER, ( const char *)
&Option, sizeof (linger))
== -1) |
7 | cerr
<< "Set
SO_LINGER option failed" <<
endl; |
|
This allows the socket to die quickly and allow the address to be reused again. Warning: This linger configuration specified may/will result in data loss upon socket termination, thus it would not have the robustness required for a banking transaction but would
be ok for a recreational app.
Broadcast:
view source
print?
1 | int iOption
= 0; //
Broadcast option to set, 0 = disables, 1 = enables |
3 | if (setsockopt(socketHandle,
SOL_SOCKET, SO_BROADCAST, ( const char *)
&iOption, sizeof ( int ))
== SOCKET_ERROR) |
5 | cerr
<< "Set
reuse address: Client set reuse address option failed" <<
endl; |
|
Struct: remoteSocketInfo.sin_addr.s_addr = htonl(INADDR_BROADCAST);
setsockopt man
page: set a particular socket option for the specified socket.
more info, pls see:
http://www.yolinux.com/TUTORIALS/Sockets.html#OPTIONS