使用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);
- }