Querying and Modifying Attributes

In this section, we will learn how to use getsockopt() and setsockopt() to query and modify the attributes of a socket, respectively.

Why would we want to query the attributes, or options, of a socket? And why would we want to set the options? The answer to both of these questions is not just to obtain the information, but to use the information gleaned from getsockopt(), if we wish, to fine-tune the behavior of the socket. To fine-tune a socket's attributes, you should use setsockopt(). Let's take an example from a real-life situation. Very often, you may want to increase the timeout on a receiving socket from 2 to 20 seconds on an extremely slow network. You would use the getsockopt() function to verify that the receiving socket's timeout is, indeed, 2 seconds. You would call it like the following:

// Retrieve the value to verify what we set ...

Res := getsockopt(skt, SOL_SOCKET, SO_RCVTIMEO, PChar(@Value),Size);

if Res = SOCKET_ERROR then

{rest of code)

Don't worry about the parameters in getsockopt(), as we will explain these shortly.

Having satisfied yourself that the timeout value is 2 seconds, call setsockopt() to set a new timeout value of 20 seconds, as the following snippet of code illustrates:

Res := setsockopt(skt, SOL_SOCKET, SO_RCVTIMEO, PChar(@Value), Size);

if Res = SOCKET_ERROR then {rest of code}

Now that we have demonstrated how to use the getsockopt() and setsockopt() functions (admittedly contrived), it's time for us to examine these prototypes, which are defined in Winsock2.pas. We will start with the getsockopt() function:

function getsockopt(s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer; stdcall;

The first parameter, s, is the socket with options that you wish to query. The second parameter, level, defines the level of the socket options. We will discuss this parameter in detail shortly. The third parameter, optname, is the name of the socket option that you wish to discover. The fourth parameter, optval, contains the options set of that level for that socket. Note that this parameter is a PChar type, so you always typecast this as a PChar variable.

In the case of the SO_RCVTIMEO option in the preceding code fragment, typecast the time in seconds as a PChar variable. (This typecasting also applies to setsockopt(), by the way.) The last parameter, optlen, defines the length of the result. For example, when you call getsockopt() with the SO_LINGER option as the optname parameter, optlen will be the size of the TLinger record (see the definition of TLinger record in Winsock2.pas). For the majority of socket options, the size of the socket option is usually the size of an integer. If a socket option was never set with setsockopt(), getsockopt() returns the default value for the socket option.

Remember from our discussion on WSAStartup() in Chapter 2 that it is not possible to get full details of Winsock 2's properties. You can get over this hurdle by calling getsockopt() to retrieve the details. For example, to retrieve information on the maximum message size (from the iMaxUdpDg field in the TWSAData record), you would call getsockopt() with the SO_MAX_MSG_SIZE option.

When you want to modify the behavior of a socket, you should call setsockopt() to set the attributes, or options, for that socket. We show its prototype, which is also defined in Winsock2.pas:

function setsockopt(s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer; stdcall;

Since the parameters for setsockopt() are similar to those for getsockopt(), we will not describe them again. However, there are two types of socket options that you must bear in mind, which are as follows:

  • Boolean options — Enables or disables a feature or behavior. To enable a Boolean option, you should set the optval parameter to a nonzero integer. Conversely, to disable the option, you should set the optval parameter to zero. The field optlen must always be equal to the size of an integer.
  • Integer options — Require an integer value or record. For other options, optval points to an integer or record that contains the desired value for the option, and optlen is the length of the integer or record.

By now, you must be wondering about the mysterious second parameter, level, that is common to both functions. The explanation is that the level parameter refers to a particular grouping of socket options. We group these options into units or, more often in Winsock parlance, into levels. Winsock 2 supports a number of levels, such as SOL_SOCKET, SOL_APPLETALK, and many others. However, unlike Winsock 2, Winsock 1.1 provides support for only two levels of socket options, SOL_SOCKET and IPPROTO_TCP Some implementations of Winsock 1.1 may support the IPPROTO_IP level. Both versions of Winsock (1 and 2) always support the SOL_SOCKET level, which is not protocol dependent. Table 6-1 tabulates the options in both SOL_SOCKET and IPPROTO_TCP levels that are common to both versions of Winsock.

As the focus in the rest of this chapter is on Microsoft's implementation of Winsock on Windows platforms, we will not cover levels that are relevant to Novell's IPX/SPX or Apple's AppleTalk or ATM protocols. The levels that we will cover here are SOL_SOCKET, IPPROTO_TCP, and IPPROTO_IP. Although Microsoft recently added a new level, SOL_IRLMP for infrared devices, we will not discuss SOL_IRLMP in this tome.

Table 6-1: Base levels

Level = SOL_SOCKET

Value

Type

Meaning

Default

SO_ACCEPTCONN

BOOL

If TRUE, socket is listening.

FALSE

SO_BROADCAST

BOOL

If TRUE, socket is configured for the transmission of broadcast messages.

FALSE

SO_DEBUG

BOOL

If TRUE, debugging is enabled.

FALSE

SO_DONTLINGER

BOOL

If TRUE, the SO_LINGER option is disabled.

TRUE

SO_DONTROUTE

BOOL

If TRUE, routing is disabled.

FALSE

SO_ERROR

Integer

Retrieves error status and clear.

0

SO_KEEPALIVE

BOOL

Keepalives are being sent.

FALSE

SO_LINGER

TLinger

Returns the current linger options.

l onoff is 0

SO_MAX_MSG_SIZE

Unsigned integer

Maximum outbound (send) size of a message for message-oriented socket types (e.g., SOCK_DGRAM). There is no provision for finding out the maximum inbound message size. This has no meaning for stream-oriented sockets.

Implementation dependent

SO_OOBINLINE

BOOL

Out-of-band data is being received in the normal data stream.

FALSE

SO_PROTOCOL_INFO

WSAPROTOCOL _INFO

Description of protocol info for protocol that is bound to this socket.

Protocol dependent

Value

Type

Meaning

Default

SO_RCVBUF

Integer

Total per-socket buffer space reserved for receives. This is unrelated to SO_MAX_MSG_ SIZE or the size of a TCP window.

Implementation dependent

SO_REUSEADDR

BOOL

The socket may be bound to an address that is already in use.

FALSE

SO_SNDBUF

Integer

Total per-socket buffer space reserved for sends. This is unrelated to SO_MAX_MSG_ SIZE or the size of a TCP window.

Implementation dependent

SO_TYPE

Integer

The type of the socket (e.g., SOCK_STREAM).

As created via socket API

PVD_CONFIG

Service provider dependent

An "opaque" data structure object from the service provider associated with socket s. This object stores the current configuration information of the service provider. The exact format of this data structure is service provider specific.

Implementation dependent

Level = IPPROTO_TCP

Value

Type

Meaning

Default

TCP_NODELAY

BOOL

Disables the Nagle algorithm for send coalescing.

Implementation dependent

TIP: Unlike Winsock 1.1, retrieving configuration information for

Winsock 2 is not easy, if not impossible, because of Winsock 2's more elaborate architecture to support multiple protocols. However, you can retrieve some of this information by calling getsockopt() with the socket option PVD_CONFIG, providing that you know the data structure of the record provided by the Winsock vendor.

The socket options that all versions of Winsock support are a subset of the BSD socket options. For those Delphi developers with a UNIX and Linux background, Tables 6-2 and 6-3 list those BSD socket options that getsockopt() and setsockopt() under Winsock do not support.

Table 6-2: BSD socket options not supported by getsockopt()

Value

Type

Meaning

SO_RCVLOWAT

Integer

Receive low water mark

SO_SNDLOWAT

Integer

Send low water mark

TCP_MAXSEG

Integer

Get TCP maximum segment size

Table 6-3: BSD socket options not supported by setsockopt()

Value

Type

Meaning

SO_ACCEPTCONN

BOOL

Socket is listening

SO_RCVLOWAT

Integer

Receive low water mark

SO_SNDLOWAT

Integer

Send low water mark

SO_TYPE

Integer

Type of socket

Table 6-4 shows a complete list of levels and their corresponding grouping of options that getsockopt() can use under Winsock 1.1 and Winsock 2. Table 6-4: Levels and options that getsockopt() can use

Level = SOL_SOCKET

Value

Type

Meaning

SO_ACCEPTCONN

BOOL

FALSE unless a WSPListen()* has been performed.

SO_BROADCAST

BOOL

Allow transmission of broadcast messages on the socket.

SO_DEBUG

BOOL

Record debugging information.

SO_DONTLINGER

BOOL

Don't block close waiting for unsent data to be sent. Setting this option is equivalent to setting SO LINGER with l onoff set to zero.

SO_DONTROUTE

BOOL

Do not route, but send directly to interface.

SO_KEEPALIVE

BOOL

Send keepalives.

SO_LINGER

TLinger

Linger on close if unsent data is present

SO_OOBINLINE

BOOL

Receive out-of-band data in the normal data stream.

SO_RCVBUF

Integer

Specify the total per-socket buffer space reserved for receives. This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window.

SO_REUSEADDR

BOOL

Allow the socket to be bound to an address that is already in use. (See bind().)

SO_SNDBUF

Integer

Specify the total per-socket buffer space reserved for sends. This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window.

Level = IPPROTO_TCP**

Value

Type

Meaning

TCP_NODELAY

BOOL

Disables the Nagle algorithm for send coalescing.

"This is the listen() function in the Winsock 2 Service Provider API, which is not discussed in this tome. "Included for backward compatibility with WinSock 1.1

There are constraints and traps that you should be aware of when using the getsockopt() and setsockopt() functions that are easily overlooked during the development process. I am often guilty of these lapses, so I will describe these 6 traps for both the wary and the not-so-wary.

A factor that you must remember is that some of these socket options are platform specific. For example, the socket option SO_EXCLUSIVEADDRUSE is only available in Winsock 2 on Windows 2000 and later. So when you use either u &

the getsockopt() or setsockopt() functions with an unsupported socket option, Winsock will return an error code of WSAENOPROTOOPT.

Another important constraint you should remember is that some of the socket options are only available for inspection after the socket is connected. For example, the option SO_CONNECT_TIME that you would use with getsockopt() to return the time (in seconds) that the socket has been connected would return an invalid value of $FFFFFFFF for a non-connected socket.

Another factor to consider is that some options only make sense with the correct socket type(s). For example, the option SO_DONTLINGER only applies to sockets of the SOCK_STREAM type.

In the rest of this chapter, we will focus on options for each level that interest us, namely, SOL_SOCKET, IPPROTO_TCP, and IPPROTO_IP. There is one level that we will not be covering in this book, SOL_IRLMP, which deals with infrared sockets. This option first appeared in Windows CE.

Option Level = SOL_SOCKET

Was this article helpful?

+1 0

Post a comment