《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选项级别下的各选项:

《ASCE1885的网络编程》---Winsock APIの套接口选项函数_第1张图片

《ASCE1885的网络编程》---Winsock APIの套接口选项函数_第2张图片

2IPPROTO_IP选项级别:

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

《ASCE1885的网络编程》---Winsock APIの套接口选项函数_第3张图片

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;

}

你可能感兴趣的:(网络编程)