使用setsockopt和getsockopt函數可以設置或讀取套接字接口的選項值
- int setsockopt(
- __in SOCKET s,
- __in int level,
- __in int optname,
- __in const char* optval,
- __in int optlen
- );
- int getsockopt(
- __in SOCKET s,
- __in int level,
- __in int optname,
- __out char* optval,
- __in_out int* optlen
- );
s是我們感興趣的套接字。level是套接字選項級別。optname是用戶指定的選項名稱。optval是一個指向變量的指針,它的大小有optlen指定,通過optval可以設置或讀取指定的選項的值。
如果沒有錯誤發生,函數返回0,否則返回SOCKET_ERROR。
套接字選項主要有兩種類型:布爾型,用於啓用或禁止套接字的某個屬性;選項參數,整形或者結構體,這隻特定的值。爲了啓動某個布爾型選項,optval應指向某個非零整數,若要禁用則指向一個零值整數,同時,optlen參數值應該等於布爾型大小,即sizeof(BOOL);對其他選項類型,optval應指向整形或者結構體,optlen這爲整型或結構體的大小。
Winsock支持的全部選項級別有IPPROTO_IP,IPPROTO_IPV6,IPPROTO_RM,IPPROTO_TCP,IPPROTO_UDP,NSPROTO_IPX,
SOL_AOOLETALK,SOL_IRLMP,SOL_SOCKET
---
//一些列類型說明
---
以SO_RCVTIMEO爲例說明SOL_SOCKET選項的使用。下面例子演示如何爲TCP/IP套接字設置並讀取接收超時值,(希望能在10秒內收到對方主動發來的數據):
- #include<stdio.h>
- #include<winsock2.h>
- #pragma comment(lib,"ws2_32.lib")
- #define TCP
- void HandleError(char *);
- int main()
- {
- WSADATA wsaData;
- WSAStartup(MAKEWORD(2,2), &wsaData);
- DWORD begin, finish;
- struct timeval tv;
- tv.tv_sec = 10000;
- tv.tv_usec = 0;
- int optlen = sizeof(tv);
- #ifdef TCP
- SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
- printf("TCP test\n");
- SOCKADDR_IN to;
- memset(&to,0,sizeof(SOCKADDR_IN));
- to.sin_family = AF_INET;
- to.sin_port = htons(5050);
- to.sin_addr.s_addr = inet_addr("202.119.24.32");
- if(SOCKET_ERROR==connect(sock,(SOCKADDR*)&to,sizeof(SOCKADDR_IN)))
- {
- HandleError("connect");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- if(SOCKET_ERROR==setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,
- (char*)&tv,optlen))
- {
- HandleError("setsockopt");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- char buf[100];
- begin = GetTickCount();
- if(SOCKET_ERROR==recv(sock,buf,100,0))
- {
- HandleError("recv");
- if(WSAETIMEDOUT==WSAGetLastError())
- {
- printf("WSAETIMEDOUT\n");
- }
- }
- finish = GetTickCount();
- #else //UDP
- SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);
- printf("UDP test\n");
- SOCKADDR_IN local;
- memset(&local,0,sizeof(SOCKADDR_IN));
- local.sin_family=AF_INET;
- local.sin_port=htons(5050);
- local.sin_addr.s_addr=INADDR_ANY;
- if(SOCKET_ERROR==bind(sock,(SOCKADDR*)&local,sizeof(SOCKADDR_IN)))
- {
- HandleError("bind");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- if(SOCKET_ERROR==setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,
- (char*)&tv,optlen))
- {
- HandleError("setsockopt");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- char buf[100];
- begin = GetTickCount();
- if(SOCKET_ERROR==recvfrom(sock,buf,100,0,NULL,NULL))
- {
- HandleError("recvfrom");
- if(WSAETIMEDOUT==WSAGetLastError())
- {
- printf("WSAETIMEDOUT\n");
- }
- }
- finish = GetTickCount();
- #endif
- printf("實際等待時間(毫秒):%d\n", finish-begin);
- memset(&tv,0,optlen);
- if(SOCKET_ERROR==getsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,
- (char*)&tv,&optlen))
- {
- HandleError("getsockopt");
- }
- printf("設置等待時間(毫秒):%d\n", tv.tv_sec);
- closesocket(sock);
- WSACleanup();
- return 0;
- }
- void HandleError(char* func)
- {
- int errCode = WSAGetLastError();
- char info[65] = {0};
- _snprintf(info,64,"%s: %d", func,errCode);
- printf(info);
- }