What do we have in this chapter?
Winsock Tutorial
Winsock: Story 1Winsock: Story 2Winsock: Story 3Winsock: Example 1Winsock: Example 2Winsock: Example 3Winsock: Example 4Winsock: Example 5Winsock: Example 6Winsock: Example 7Winsock: Example 8Winsock: Example 9Winsock: Example 10Winsock: Example 11Winsock: Example 12Winsock: Reference 1Winsock: Reference 2Winsock: Reference 3Winsock: Reference 4Another Complete and Advanced C & Winsock2 Programming Tutorial |
My Training Period: hours
Machine’s OS is standalone Windows Xp Pro with SP2 except whenever mentioned. Compiler used was Visual C++ 2003 .Net 1.1. Beware the codes that span more than one line. Program examples have been tested for Non Destructive Test. All information compiled for Windows 2000 (NT5.0) above and...
Abilities:
getsockopt()
Return Values
If no error occurs, getsockopt() returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError().
|
||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||
Remarks
The getsockopt() function retrieves the current value for a socket option associated with a socket of any type, in any state, and stores the result in optval. Options can exist at multiple protocol levels, but they are always present at the uppermost socket level. Options affect socket operations, such as the packet routing and OOB data transfer. The value associated with the selected option is returned in the buffer optval. The integer pointed to by optlen should originally contain the size of this buffer; on return, it will be set to the size of the value returned. For SO_LINGER, this will be the size of a LINGER structure. For most other options, it will be the size of an integer. The application is responsible for allocating any memory space pointed to directly or indirectly by any of the parameters it specified. If the option was never set with setsockopt(), then getsockopt() returns the default value for the option. The following options are supported for getsockopt(). The Type column identifies the type of data addressed by optval.
For level = SOL_SOCKET
|
Value |
Type |
Meaning |
SO_ACCEPTCONN |
BOOL |
Socket is listening. |
SO_BROADCAST |
BOOL |
Socket is configured for the transmission and receipt of broadcast messages. |
SO_CONDITIONAL_ACCEPT |
BOOL |
Returns current socket state, either from a previous call to setsockopt() or the system default. |
SO_DEBUG |
BOOL |
Debugging is enabled. |
SO_DONTLINGER |
BOOL |
If TRUE, the SO_LINGER option is disabled. |
SO_DONTROUTE |
BOOL |
Routing is disabled. Succeeds but is ignored on AF_INET sockets; fails on AF_INET6 sockets with WSAENOPROTOOPT. Not supported on ATM sockets. |
SO_ERROR |
int |
Retrieves error status and clear. |
SO_GROUP_ID |
GROUP |
Reserved. |
SO_GROUP_PRIORITY |
int |
Reserved. |
SO_KEEPALIVE |
BOOL |
Keep-alives are being sent. Not supported on ATM sockets. |
SO_LINGER |
LINGER structure |
Returns the current linger options. |
SO_MAX_MSG_SIZE |
unsigned int |
Maximum size of a message for message-oriented socket types (for example, SOCK_DGRAM). Has no meaning for stream oriented sockets. |
SO_OOBINLINE |
BOOL |
OOB data is being received in the normal data stream. |
SO_PROTOCOL_INFO |
WSAPROTOCOL_INFO |
Description of protocol information for protocol that is bound to this socket. |
SO_RCVBUF |
int |
Buffer size for receives. |
SO_REUSEADDR |
BOOL |
The socket can be bound to an address which is already in use. Not applicable for ATM sockets. |
SO_SNDBUF |
int |
Buffer size for sends. |
SO_TYPE |
int |
The type of the socket (for example, SOCK_STREAM). |
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. |
|
Table 3 |
||
For level = IPPROTO_TCP
|
Value |
Type |
Meaning |
|
TCP_NODELAY |
BOOL |
Disables the Nagle algorithm for send coalescing. |
|
Table 4 |
||
For level = NSPROTO_IPX
Windows NT supports all IPX (Netware-obsolete?) options. Windows Me/98/95 supports only the following options:
IPX_PTYPE
IPX_FILTERPTYPE
IPX_DSTYPE
IPX_RECVHDR
IPX_MAXSIZE
IPX_ADDRESS
|
Value |
Type |
Meaning |
IPX_PTYPE |
int |
Retrieves the IPX packet type. |
IPX_FILTERPTYPE |
int |
Retrieves the receive filter packet type |
IPX_DSTYPE |
int |
Obtains the value of the data stream field in the SPX header on every packet sent. |
IPX_EXTENDED_ADDRESS |
BOOL |
Finds out whether extended addressing is enabled. |
IPX_RECVHDR |
BOOL |
Finds out whether the protocol header is sent up on all receive headers. |
IPX_MAXSIZE |
int |
Obtains the maximum data size that can be sent. |
IPX_ADDRESS |
IPX_ADDRESS_DATA structure |
Obtains information about a specific adapter to which IPX is bound. Adapter numbering is base zero. The adapternum member is filled in upon return. |
IPX_GETNETINFO |
IPX_NETNUM_DATA structure |
Obtains information about a specific IPX network number. If not available in the cache, uses RIP to obtain information. |
IPX_GETNETINFO_NORIP |
IPX_NETNUM_DATA structure |
Obtains information about a specific IPX network number. If not available in the cache, will not use RIP to obtain information, and returns error. |
IPX_SPXGETCONNECTIONSTATUS |
IPX_SPXCONNSTATUS_DATA structure |
Retrieves information about a connected SPX socket. |
IPX_ADDRESS_NOTIFY |
IPX_ADDRESS_DATA structure |
Retrieves status notification when changes occur on an adapter to which IPX is bound. |
IPX_MAX_ADAPTER_NUM |
int |
Retrieves maximum number of adapters present, numbered as base zero. |
IPX_RERIPNETNUMBER |
IPX_NETNUM_DATA structure |
Similar to IPX_GETNETINFO, but forces IPX to use RIP for resolution, even if the network information is in the local cache. |
IPX_IMMEDIATESPXACK |
BOOL |
Directs SPX connections not to delay before sending an ACK. Applications without back-and-forth traffic should set this to TRUE to increase performance. |
|
Table 5 |
||
BSD options not supported for getsockopt() are as shown in the following table.
|
Value |
Type |
Meaning |
SO_RCVLOWAT |
int |
Receives low watermark. |
SO_RCVTIMEO |
int |
Receives time-out. |
SO_SNDLOWAT |
int |
Sends low watermark. |
SO_SNDTIMEO |
int |
Sends time-out. |
TCP_MAXSEG |
int |
Receives TCP maximum-segment size. |
|
Table 6 |
||
When using the recv() function, if no data arrives during the period specified in SO_RCVTIMEO, the recv() function completes. In Windows versions prior to Windows 2000, any data received subsequently fails with WSAETIMEDOUT. In Windows 2000 and later, if no data arrives within the period specified in SO_RCVTIMEO the recv() function returns WSAETIMEDOUT, and if data is received, recv() returns SUCCESS. Calling getsockopt() with an unsupported option will result in an error code of WSAENOPROTOOPT being returned from WSAGetLastError().
SO_DEBUG - Windows Sockets service providers are encouraged (but not required) to supply output debug information if the SO_DEBUG option is set by an application. The mechanism for generating the debug information and the form it takes are beyond the scope of this document.
SO_ERROR - The SO_ERROR option returns and resets the per socket–based error code, which is different from the per thread based–error code that is handled using the WSAGetLastError() and WSASetLastError() function calls. A successful call using the socket does not reset the socket based error code returned by the SO_ERROR option.
SO_GROUP_ID - This option is reserved. This option is also exclusive to getsockopt(); the value should be null.
SO_GROUP_PRIORITY - This option is reserved. Group priority indicates the priority of the specified socket relative to other sockets within the socket group. Values are nonnegative integers, with zero corresponding to the highest priority. Priority values represent a hint to the underlying service provider about how potentially scarce resources should be allocated. For example, whenever two or more sockets are both ready to transmit data, the highest priority socket (lowest value for SO_GROUP_PRIORITY) should be serviced first, with the remainder serviced in turn according to their relative priorities. The WSAENOPROTOOPT error code is indicated for non-group sockets or for service providers that do not support group sockets.
SO_KEEPALIVE - An application can request that a TCP/IP service provider enable the use of keep-alive packets on TCP connections by turning on the SO_KEEPALIVE socket option. A Windows Sockets provider need not support the use of keep-alive: if it does, the precise semantics are implementation-specific but should conform to section 4.2.3.6 of RFC 1122: Requirements for Internet Hosts - Communication Layers. If a connection is dropped as the result of keep-alives the error code WSAENETRESET is returned to any calls in progress on the socket, and any subsequent calls will fail with WSAENOTCONN. SO_KEEPALIVE is not supported on ATM sockets, and requests to enable the use of keep-alive packets on an ATM socket results in an error being returned by the socket.
SO_LINGER - SO_LINGER controls the action taken when unsent data is queued on a socket and a closesocket() is performed. See closesocket() for a description of the way in which the SO_LINGER settings affect the semantics of closesocket(). The application gets the current behavior by retrieving a LINGER structure (pointed to by the optval parameter).
SO_MAX_MSG_SIZE - This is a get-only socket option that indicates the maximum outbound (send) size of a message for message-oriented socket types (for example, SOCK_DGRAM) as implemented by a particular service provider. It has no meaning for byte stream oriented sockets. There is no provision to find out the maximum inbound–message size.
SO_PROTOCOL_INFO - This is a get-only option that supplies the WSAPROTOCOL_INFO structure associated with this socket.
SO_SNDBUF - When a Windows Sockets implementation supports the SO_RCVBUF and SO_SNDBUF options, an application can request different buffer sizes (larger or smaller). The call to setsockopt() can succeed even if the implementation did not provide the whole amount requested. An application must call this function with the same option to check the buffer size actually provided.
|
getsockopt() Program Example
The following code sample demonstrates the use of the getsockopt() function.
#include <stdio.h>
#include "winsock2.h"
void main()
{
// Declare variables
WSADATA wsaData;
SOCKET ListenSocket;
sockaddr_in service;
// Initialize Winsock, request Winsock 2.2
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != NO_ERROR)
printf("Error at WSAStartup().\n");
else
printf("WSAStartup() is OK.\n");
// Create a listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket()\n");
WSACleanup();
return;
}
else
printf("socket() is OK.\n");
// Bind the socket to the local IP address and port 55555
hostent* thisHost;
char* ip;
u_short port;
port = 55555;
thisHost = gethostbyname("");
ip = inet_ntoa(*(struct in_addr *)*thisHost->h_addr_list);
// Try running this program on machine using live IP...
printf("\nIP address is: %s.\n", ip);
printf("Hostname is: %s.\n", thisHost->h_name);
printf("Address type: %i.\n\n", thisHost->h_addrtype);
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
if (bind(ListenSocket,(SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
printf("bind() failed.\n");
closesocket(ListenSocket);
return;
}
else
printf("bind() is OK.\n");
// Initialize variables and call getsockopt().
// The SO_ACCEPTCONN parameter is a socket option
// that tells the function to check whether the
// socket has been put in listening mode or not.
// The various socket options return different
// information about the socket. This call should
// return 0 to the optVal parameter, since the socket
// is not in listening mode.
int optVal;
int optLen = sizeof(int);
if (getsockopt(ListenSocket,
SOL_SOCKET,
SO_ACCEPTCONN,
(char*)&optVal,
&optLen) != SOCKET_ERROR)
printf("Initial SockOpt value: %ld\n", optVal);
// Put the listening socket in listening mode.
if (listen(ListenSocket, 100) == SOCKET_ERROR)
{
printf("Error listening.\n");
}
else
printf("listen() is OK. Socket in listening mode...\n");
// Call getsockopt() again to verify that the socket is in listening mode.
if (getsockopt(ListenSocket,
SOL_SOCKET,
SO_ACCEPTCONN,
(char*)&optVal,
&optLen) != SOCKET_ERROR)
printf("Then, SockOpt value: %ld.\n", optVal);
else
printf("Error getsockopt().\n");
WSACleanup();
return;
}
Sample output:

Figure 1
For IrDA Sockets:
The af_irda.h header file must be explicitly included.
Windows returns WSAENETDOWN to indicate the underlying transceiver driver failed to initialize with the IrDA protocol stack.
IrDA supports several special socket options:
|
Value |
Type |
Meaning |
|
IRLMP_ENUMDEVICES |
*DEVICELIST |
Describes devices in range. |
|
IRLMP_IAS_QUERY |
*IAS_QUERY |
Retrieve IAS attributes. |
|
Table 7 |
||
Before an IrDA socket connection can be initiated, a device address must be obtained by performing a getsockopt(,,IRLMP_ENUMDEVICES,,) function call, which returns a list of all available IrDA devices. A device address returned from the function call is copied into a SOCKADDR_IRDA structure, which in turn is used by a subsequent call to the connect() function call. Discovery can be performed in two ways:
First, performing a getsockopt() function call with the IRLMP_ENUMDEVICES option causes a single discovery to be run on each idle adapter. The list of discovered devices and cached devices (on active adapters) is returned immediately. The following code demonstrates this approach.
SOCKADDR_IRDA DestSockAddr = {AF_IRDA, 0, 0, 0, 0, "SampleIrDAService"};
#define DEVICE_LIST_LEN 10
unsigned char DevListBuff[sizeof(DEVICELIST) –
sizeof(IRDA_DEVICE_INFO) + (sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
int DevListLen = sizeof(DevListBuff);
PDEVICELIST pDevList = (PDEVICELIST) &DevListBuff;
pDevList->numDevice = 0;
// Sock is not in connected state
if (getsockopt(Sock, SOL_IRLMP, IRLMP_ENUMDEVICES, (char *) pDevList, &DevListLen) == SOCKET_ERROR)
{
// WSAGetLastError
}
if (pDevList->numDevice == 0)
{
// no devices discovered or cached
// not a bad idea to run a couple of times
}
else
{
// one per discovered device
for (i = 0; i < (int) pDevList->numDevice; i++)
{
// typedef struct _IRDA_DEVICE_INFO
// {
// u_char irdaDeviceID[4];
// char irdaDeviceName[22];
// u_char irdaDeviceHints1;
// u_char irdaDeviceHints2;
// u_char irdaCharSet;
// } _IRDA_DEVICE_INFO;
// pDevList->Device[i]. see _IRDA_DEVICE_INFO for fields
// display the device names and let the user select one
}
}
// assume the user selected the first device [0]
memcpy(&DestSockAddr.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);
if (connect(Sock, (const struct sockaddr *) &DestSockAddr, sizeof(SOCKADDR_IRDA)) == SOCKET_ERROR)
{
// WSAGetLastError
}
The second approach to performing discovery of IrDA device addresses is to perform a lazy discovery; in this approach, the application is not notified until the discovered devices list changes from the last discovery run by the stack. The DEVICELIST structure shown in the Type column in the previous table is an extendible array of device descriptions. IrDA fills in as many device descriptions as can fit in the specified buffer. The device description consists of a device identifier necessary to form a sockaddr_irda structure, and a displayable string describing the device. The IAS_QUERY structure shown in the Type column in the previous table is used to retrieve a single attribute of a single class from a peer device's IAS database. The application specifies the device and class to query and the attribute and attributes type. Note that the device would have been obtained previously by a call to getsockopt(IRLMP_ENUMDEVICES). It is expected that the application allocates a buffer, of the necessary size, for the returned parameters. Many level socket options are not meaningful to IrDA; only SO_LINGER and SO_DONTLINGER are specifically supported.
Further reading and digging:
Linux Sockets: Story and program examples.
A complete info on Windows socket reference from MSDN which include managed and unmanaged API doc.
Structure, enum, union and typedef story can be found struct, enum, union & typedef tutorial.
For Multibytes, Unicode characters and Localization please refer to Multibyte, Unicode and wide characters (Story) and Win32 Windows & Users tutorial (Implementation).
Windows data type information is Win32 - Windows data types.
Check the best selling C / C++ and Windows books at Amazon.com.