使用setsockopt和getsockopt函数可以设置或读取套接字接口的选项值

  1. int setsockopt( 
  2.   __in          SOCKET s, 
  3.   __in          int level, 
  4.   __in          int optname, 
  5.   __in          const char* optval, 
  6.   __in          int optlen 
  7. ); 

  1. int getsockopt( 
  2.   __in          SOCKET s, 
  3.   __in          int level, 
  4.   __in          int optname, 
  5.   __out         char* optval, 
  6.   __in_out      int* optlen 
  7. ); 

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秒内收到对方主动发来的数据):

  1. #include<stdio.h> 
  2. #include<winsock2.h> 
  3. #pragma comment(lib,"ws2_32.lib") 
  4.  
  5. #define TCP 
  6.  
  7. void HandleError(char *); 
  8.  
  9. int main() 
  10.     WSADATA wsaData; 
  11.     WSAStartup(MAKEWORD(2,2), &wsaData); 
  12.     DWORD begin, finish; 
  13.      
  14.     struct timeval tv; 
  15.     tv.tv_sec = 10000; 
  16.     tv.tv_usec = 0; 
  17.     int optlen = sizeof(tv); 
  18.      
  19. #ifdef TCP 
  20.     SOCKET sock = socket(AF_INET,SOCK_STREAM,0); 
  21.     printf("TCP test\n"); 
  22.     SOCKADDR_IN to; 
  23.     memset(&to,0,sizeof(SOCKADDR_IN)); 
  24.     to.sin_family = AF_INET; 
  25.     to.sin_port = htons(5050); 
  26.     to.sin_addr.s_addr = inet_addr("202.119.24.32"); 
  27.     if(SOCKET_ERROR==connect(sock,(SOCKADDR*)&to,sizeof(SOCKADDR_IN))) 
  28.     { 
  29.         HandleError("connect"); 
  30.         closesocket(sock); 
  31.         WSACleanup(); 
  32.         return -1; 
  33.     } 
  34.     if(SOCKET_ERROR==setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO, 
  35.                                 (char*)&tv,optlen)) 
  36.     { 
  37.         HandleError("setsockopt"); 
  38.         closesocket(sock); 
  39.         WSACleanup(); 
  40.         return -1; 
  41.     } 
  42.     char buf[100]; 
  43.     begin = GetTickCount(); 
  44.     if(SOCKET_ERROR==recv(sock,buf,100,0)) 
  45.     { 
  46.         HandleError("recv"); 
  47.         if(WSAETIMEDOUT==WSAGetLastError()) 
  48.         { 
  49.             printf("WSAETIMEDOUT\n"); 
  50.         } 
  51.     } 
  52.     finish = GetTickCount(); 
  53. #else //UDP 
  54.     SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); 
  55.     printf("UDP test\n"); 
  56.     SOCKADDR_IN local; 
  57.     memset(&local,0,sizeof(SOCKADDR_IN)); 
  58.     local.sin_family=AF_INET; 
  59.     local.sin_port=htons(5050); 
  60.     local.sin_addr.s_addr=INADDR_ANY; 
  61.     if(SOCKET_ERROR==bind(sock,(SOCKADDR*)&local,sizeof(SOCKADDR_IN))) 
  62.     { 
  63.         HandleError("bind"); 
  64.         closesocket(sock); 
  65.         WSACleanup(); 
  66.         return -1; 
  67.     } 
  68.     if(SOCKET_ERROR==setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO, 
  69.                                 (char*)&tv,optlen)) 
  70.     { 
  71.         HandleError("setsockopt"); 
  72.         closesocket(sock); 
  73.         WSACleanup(); 
  74.         return -1; 
  75.     } 
  76.     char buf[100]; 
  77.     begin = GetTickCount(); 
  78.     if(SOCKET_ERROR==recvfrom(sock,buf,100,0,NULL,NULL)) 
  79.     { 
  80.         HandleError("recvfrom"); 
  81.         if(WSAETIMEDOUT==WSAGetLastError()) 
  82.         { 
  83.             printf("WSAETIMEDOUT\n"); 
  84.         } 
  85.     } 
  86.     finish = GetTickCount(); 
  87. #endif 
  88.     printf("实际等待时间(毫秒):%d\n", finish-begin); 
  89.     memset(&tv,0,optlen); 
  90.     if(SOCKET_ERROR==getsockopt(sock,SOL_SOCKET,SO_RCVTIMEO, 
  91.                                 (char*)&tv,&optlen)) 
  92.     { 
  93.         HandleError("getsockopt"); 
  94.     } 
  95.     printf("设置等待时间(毫秒):%d\n", tv.tv_sec); 
  96.     closesocket(sock); 
  97.     WSACleanup(); 
  98.     return 0; 
  99.  
  100. void HandleError(char* func) 
  101.     int errCode = WSAGetLastError(); 
  102.     char info[65] = {0}; 
  103.     _snprintf(info,64,"%s:   %d", func,errCode); 
  104.     printf(info);