《ASCE1885的网络编程》---Winsock APIの套接口选项函数

套接口在建立以后,可以通过设置套接口的属性对套接口的行为和操作进行控制,这就要使用套接口选项设置函数setsockopt()。也可以在套接口上进行操作前首先查看套接口属性的设置情况,这就要使用套接口选项获取函数getsockopt()

int setsockopt(

  __in  SOCKET s, //指定一个有效的套接口

  __in  int level, //套接口选项定义的级别,常用的有SOL_SOCKETIPPROTO_IPIPPROTO_TCP

  __in  int optname, //需设置的套接口选项,选项的名称是在Winsock头文件中定义的常量值

  __in  const char *optval, //指向存放选项值缓冲区的指针

  __in  int optlen //指向optval缓冲区长度的指针

);

int getsockopt(

  __in     SOCKET s, //指定一个有效的套接口

  __in     int level, //套接口选项定义的级别,常用的有SOL_SOCKETIPPROTO_IPIPPROTO_TCP

  __in     int optname, //需获取的套接口选项,选项的名称是在Winsock头文件中定义的常量值

  __out    char *optval, //指向存放选项值缓冲区的指针

  __inout  int *optlen //指向optval缓冲区长度的指针

);

 

若函数调用成功,则setsockopt()getsockopt()函数都返回0。若调用时发生错误,则返回SOCKET_ERROR错误信息,应用程序通过WSAGetLastError()函数获取对错误信息的进一步说明

 

1SOL_SOCKET选项级别:

SOL_SOCKET选项级别主要针对传输层协议(TCPUDP)。在SOL_SOCKET选项级别下,套接口的选项有两种类型:一种是值为布尔型(BOOL)的选项,这种选项可以允许或禁止一种特性;另一种是值为整型(int)或结构型(Struct Linger)的选项,这种选项可以用来设置系统工作时的某些参数。

对于布尔型选项,oprlen应等于sizeof(int);对于非布尔型的其他选项,optval应该指向包含所需选项的整型量或结构量,而optlen则为整型量或结构量的长度。

还要注意,套接口的有些属性值即可以设置(setsockopt),也可以获取(getsockopt),但有些套接口属性只能获取或只能设置。

SOL_SOCKET选项级别下的各选项:

 

 

2IPPROTO_IP选项级别:

IPPROTO_IP级别的套接口选项是针对网络层协议的,即IPv4协议,这些选项字段的声明大都放在Winsock.hWinSock2.h这两个头文件中。该选项级别包括的主要选项如下表:

 

3IPPROTO_TCP选项级别:

该选项是针对TCP协议的,在Winsock中仅有一个IPPROTO_TCP级别的选项,即TCP_NODELAY选项,该选项用来打开或关闭Nagle算法。如果该选项为TRUE,则在对应的套接口上禁止使用Nagle算法。在系统默认情况下,Nagle算法是打开的,该选项只适用于流式套接口(SOCK_STREAM),其地址族是AF_INET

Nagle算法将未确认的数据存入缓冲区,直到蓄足一个包后一起发送,这样做的好处是可以减少主机发送的零碎小数据包的数目,以减少网络通信的开销,提供系统的吞吐量。但对于某些应用来说,这种算法将降低系统性能,例如交互性较强的Telnet应用程序,用户可通过它登录另一台远程机器,然后向其传送命令。通常,用户每秒只会进行少量的键击,若使用Nagle算法,便会造成响应的迟钝,甚至造成对方主机不予应答的错觉。此时,就应该使用TCP_NODELAY选项将此算法关闭。应用程序编写者只有在确切了解它的效果并在确实需要的情况下,才可设置TCP_NODELAY选项,因为一般的应用中如果设置该选项,则对网络性能有明显的负面影响。

 

下面的代码演示的是setsockopt函数的使用:

#include <winsock2.h>

#include <windows.h>

#include <stdio.h>

 

#pragma comment(lib, "ws2_32.lib")

 

int main()

{

    //---------------------------------------

    // Declare variables

    WSADATA wsaData;

    SOCKET ListenSocket;

    sockaddr_in service;

   

    //---------------------------------------

    // Initialize Winsock

    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

    if(iResult != NO_ERROR)

        printf("Error at WSAStartup/n");

   

    //---------------------------------------

    // Create a listening socket

    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(ListenSocket == INVALID_SOCKET)

    {

        printf("Error at socket()/n");

        WSACleanup();

        return 1;

    }

   

    //---------------------------------------

    // Bind the socket to the local IP address

    // and port 27015

    hostent* thisHost;

    char* ip;

    u_short port;

    port = 27015;

    thisHost = gethostbyname("");

    ip = inet_ntoa(*(struct in_addr*)*thisHost->h_addr_list);

   

    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);   

        WSACleanup();                 

        return 1;

    }

   

    //---------------------------------------

    // Initialize variables and call setsockopt.

    // The SO_KEEPALIVE parameter is a socket option

    // that makes the socket send keepalive messages

    // on the session. The SO_KEEPALIVE socket option

    // requires a boolean value to be passed to the

    // setsockopt function. If TRUE, the socket is

    // configured to send keepalive messages, if FALSE

    // the socket configured to NOT send keepalive messages.

    // This section of code tests the setsockopt function

    // by checking the status of SO_KEEPALIVE on the socket

    // using the getsockopt function.

    BOOL bOptVal = TRUE;

    int bOptLen = sizeof(BOOL);

    int iOptVal;

    int iOptLen = sizeof(int);

   

    if(getsockopt(ListenSocket, SOL_SOCKET, SO_KEEPALIVE,

                     (char*)&iOptVal, &iOptLen) != SOCKET_ERROR)

    {

        printf("SO_KEEPALIVE value: %ld/n", iOptVal);

    }

   

    if(setsockopt(ListenSocket, SOL_SOCKET, SO_KEEPALIVE,

                      (char*)&bOptVal, bOptLen) != SOCKET_ERROR)

    {

        printf("Set SO_KEEPALIVE: ON/n");                 

    }

   

    if(getsockopt(ListenSocket, SOL_SOCKET, SO_KEEPALIVE,

                      (char*)&iOptVal, &iOptLen) != SOCKET_ERROR)

    {

        printf("SO_KEEPALIVE value: %ld/n", iOptVal);

    }

   

    WSACleanup();

    system("pause");

    return 0;   

}

 

=======================================================

下面代码演示了getsockopt函数的使用:

#include <winsock2.h>

#include <stdio.h>

#include <windows.h>

 

#pragma comment(lib, "ws2_32.lib")

 

void main() {

        

         //---------------------------------------

         // Declare variables

         WSADATA wsaData;

         SOCKET ListenSocket;

         sockaddr_in service;

        

         //---------------------------------------

         // Initialize Winsock

         int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );

         if( iResult != NO_ERROR )

                   printf("Error at WSAStartup/n");

        

         //---------------------------------------

         // Create a listening socket

         ListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

         if (ListenSocket == INVALID_SOCKET) {

                   printf("Error at socket()/n");

                   WSACleanup();

                   return;

         }

        

         //---------------------------------------

         // Bind the socket to the local IP address

         // and port 27015

         hostent* thisHost;

         char* ip;

         u_short port;

         port = 27015;

         thisHost = gethostbyname("");

         ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);

        

         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;

         }

        

         //---------------------------------------

         // 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("SockOpt Value: %ld/n", optVal);

        

         //---------------------------------------

         // Put the listening socket in listening mode.

         if (listen( ListenSocket, 100 ) == SOCKET_ERROR) {

                   printf("error listening/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("SockOpt Value: %ld/n", optVal);

        

         WSACleanup();

         return;

}

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值