您的位置:首页 > 理论基础 > 计算机网络

Windows的网络编程-之五-套接字选项和I/O控制

2012-01-02 16:45 363 查看

1 套接字选项和I/O控制

1.1 套接字选项

intgetsockopt( SOCKET s, int level, int optname, char* optval, int* optlen );

intsetsockopt( SOCKET s, int level, int optname, const char* optval, int optlen );

1.1.1 SOL_SOCKET选项级别

1.1.1.1 SO_ACCEPTCONN

选项值类型
get/set
Winsock
说明
bool
get
1+
如果已通过listen( )将套接字置入监听模式,
这个选项就会返回TRUE。
SOCK_DGRAM类型的套接字不支持这一选项。

1.1.1.2 SO_BROADCAST

选项值类型
get/set
Winsock
说明
bool
get/set
1+
TRUE,套接字可以收发广播数据
SOCK_STREAM类型的套接字不支持这一选项。
要想接收一条广播消息,首先必须启用广播选项,然后使用某个数据报接收函数recvfrom( )或WSARecvfrom()。另外一种方法是把套接字通过调用connect( )或WSAConnect()与广播地址连接起来,再调用recv( )或WSARecv( )来实现的。对UDP广播来说,必须指定一个端口号,以便向它发送数据报;接收端也必须请求在这个端口上接收广播数据。对UDP来说,存在着一个特殊的广播地址,所有广播数据均应发至该地址。这个地址便是255.255.255.255。

通常,只有在发送广播数据报时,才需要设置SO_BROADCAST选项。要想接收一个广播数据报,只需在指定的端口上,对进入的数据报进行监听即可。

1.1.1.3 SO_CONNECT_TIME

选项值类型
get/set
Winsock
说明
int
get
1+
返回套接字建立连接的时间,以秒为单位
该选项最常见的用法是和AcceptEx( )一道使用。AcceptEx()要求为进入的客户机连接请求提供一个有效的套接字。该选项可在该套接字上调用,以判断连接是否已经建立,以及建立了多久的时间。若套接字当前尚未连接,返回值便是0xFFFFFFFF。

1.1.1.4 SO_DONTROUTE

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,忽略路由表的存在,
通过套接字绑定的那个接口直接将数据传送出去。
如果是TRUE,等同于将参数flag设置为MSG_DONTROUTE,然后调用send( )。

1.1.1.5 SO_EXCLUSIVEADDRUSE

选项值类型
get/set
Winsock
说明
bool
get/set
2+
如果是TRUE,套接字绑定的那个本地端口
就不能重新被另一个进程使用

1.1.1.6 SO_KEEPALIVE

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,套接字就会在会话过程中发送keepalive消息
SOCK_DGRAM类型的套接字不支持这一选项。

1.1.1.7 SO_LINGER

选项值类型
get/set
Winsock
说明
struct linger
get/set
1+
设置或获取当前的拖延时间
SOCK_DGRAM类型的套接字不支持这一选项。
SO_LINGER用于控制在执行closesocket()后,套接字上正在排队的数据如何处理。

typedefstruct linger

{

u_short l_onoff; // 是否linger

u_short l_linger; // 单位是秒

}linger;

若l_onoff是一个非零值,l_linger指定一段拖延时间,此时的关闭方式称为从容关闭,closesocket( )会在一个阻塞套接字上进入阻塞状态,直到剩余的数据全部发出或接收。如果超过规定的时间,所有尚未发送或接收的数据都会丢弃。

如果假如l_onoff是一个非零值,但l_linger为0,此时的关闭方式称为强行关闭,便不用担心closesocket( )会进入阻塞状态,即使队列中的数据尚未发送或者尚未发出收到确认。

1.1.1.8 SO_MAX_MSG_SIZE

选项值类型
get/set
Winsock
说明
unsigned int
get
2+
获取消息的最大长度
只适用于面向消息的套接字类型

1.1.1.9 SO_PROTOCOL_INFO

选项值类型
get/set
Winsock
说明
WSAPROTOCOL_INFO
get
2+
获取套接字协议的特征

1.1.1.10 SO_RCVBUF

选项值类型
get/set
Winsock
说明
int
get/set
1+
用于返回或设置分配给套接字的接收缓冲区大小

1.1.1.11 SO_REUSEADDR

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,套接字就可以和正被使用的地址绑定到一起,
或与处在TIME_WAIT状态的地址绑定到一起
默认情况下,套接字不能和一个正在被使用的本地地址绑定到一起

1.1.1.12 SO_SNDBUF

选项值类型
get/set
Winsock
说明
int
get/set
1+
用于返回或设置分配给套接字的发送缓冲区大小

1.1.1.13 SO_TYPE

选项值类型
get/set
Winsock
说明
int
get
1+
返回指定套接字的类型
套接字类型包括SOCK_DGRAM、SOCK_STREAM、SOCK_SEQPACKET、SOCK_RDM和SOCK_RAW等。

1.1.1.14 SO_SNDTIMEO

选项值类型
get/set
Winsock
说明
int
get/set
1+
获取或设置阻塞套接字上的数据发送超时时间(毫秒)
如果要使用SO_SNDTIMEO选项并用WSASocket()创建套接字,必须在参数dwFlags中指定WSA_FLAG_OVERLAPPED。

1.1.1.15 SO_RCVTIMEO

选项值类型
get/set
Winsock
说明
int
get/set
1+
获取或设置阻塞套接字上的数据接收超时时间(毫秒)
如果要使用SO_RCVTIMEO选项并用WSASocket()创建套接字,必须在参数dwFlags中指定WSA_FLAG_OVERLAPPED。

1.1.1.16 SO_OOBINLINE

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,
带外数据就会以内嵌方式在普通数据流中返回
SOCK_DGRAM类型的套接字不支持这一选项。
默认情况下,带外数据不是内嵌传送的,也就是说如果设置MSG_OOB标志调用一个接收函数,便会读取OOB数据。

如果设置了这个选项,OOB数据就会出现在一个接收函数返回的数据流中。

1.1.2 IPPROTO_IP选项级别

1.1.2.1 IP_OPTIONS

选项值类型
get/set
Winsock
说明
char[ ]
get/set
1+
设置或获取IP头中的可选选项部分
设置一个IP选项时,传至setsockopt( )的数据采用如下的数据结构,最长可达40字节:

代码
长度
偏移
选项数据
1 byte
1 byte
1 byte
37 byte
代码字段指定IP选项类型。

长度字段指定IP选项头的长度。

偏移字段指定数据部分的起始偏移位置。

在下面的代码中,我们设置一个记录路由的选项。注意:我们定义的结构只占用了39字节。系统会自动进行填充,将其长度保持为一个字(32 bit)的整数倍。

struct ip_option_hdr

{

unsigned char code; //1个字节

unsigned char length; //1个字节

unsigned char offset; //1个字节

unsigned long addrs[9]; //36个字节

} opthdr;

……;

memset( &opthdr, 0, sizeof(opthdr) );

opthdr.code=0x7;

opthdr.length=39;

opthdr.offset=4;

ret = setsockopt( s, IPPROTO_IP,IP_OPTIONS, (char *)&opthdr, sizeof(opthdr) );

1.1.2.2 IP_HDRINCL

选项值类型
get/set
Winsock
说明
bool
get/set
2+
如果是TRUE,发送函数会将IP头包括在发送数据的前面,
所以接收函数获取的数据也包括IP头。

1.1.2.3 IP_TOS

选项值类型
get/set
Winsock
int
get/set
1+

1.1.2.4 IP_TTL

选项值类型
get/set
Winsock
int
get/set
1+

1.1.2.5 IP_MULTICAST_IF

选项值类型
get/set
Winsock
说明
unsigned long
get/set
1+
获取或设置发送多播数据的接口
如下例所示:

unsigned long mcastIF = inet_addr("129.113.43.128");

ret = setsockopt( s, IPPROTO_IP, IP_MULTICAST_IF, (char*)&mcastIF, sizeof(mcastIF) );

1.1.2.6 IP_MULTICAST_TTL

选项值类型
get/set
Winsock
int
get/set
1+
多播数据报采用的默认TTL设定是1

1.1.2.7 IP_MULTICAST_LOOP

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,多播数据将返回套接字
如果设为TRUE(默认值),在发送IP多播数据的时候,如果套接字是多播组的一名成员,数据便会返至套接字。如果设为FALSE,发出的多播数据不会返回至套接字。

1.1.2.8 IP_ADD_MEMBERSHIP

选项值类型
get/set
Winsock
说明
struc ip_mreq
set
1+
将套接字加入一个指定的IP多播组
要想将套接字加入一个多播组,需要用socket( )来创建地址家族为AF_INET的一个套接字,同时将套接字的类型设为SOCK_DGRAM。

structip_mreg

{

struct in_addr imr_multiaddr;

struct in_addr imr_interface;

};

1.1.2.9 IP_DROP_MEMBERSHIP

选项值类型
get/set
Winsock
说明
struct ip_mreq
set
1+
将套接字从指定的IP组内删去

1.1.2.10 IP_DONTFRAGMENT

选项值类型
get/set
Winsock
说明
bool
get/set
1+
如果是TRUE,就不对IP数据报进行分段
如果一个IP数据报的大小已经超过了MTU,但未在IP头内设置分段标志,这个数据报就会被丢弃,同时向发送者返回一条ICMP错误消息。

1.2 标准I/O控制命令

intioctlsocket( SOCKETs, long cmd, u_long* argp );

intWSAIoctl( SOCKET s, DWORD dwIoControlCode,

LPVOIDlpvInBuffer, DWORD cbInBuffer,

LPVOIDlpvOutBuffer, DWORD cbOutBuffer,

LPDWORDlpcbBytesReturned,

LPWSAOVERLAPPEDlpOverlapped,

LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine

);

参数lpcbBytesReturned是实际返回的字节数。

1.2.1 FIONBIO

函数
输入
输出
Winsock
说明
两者均可
unsigned long

1+
将套接字设为非阻塞模式
默认情况下,所有套接字在创建好后都是阻塞套接字。

若设为非阻塞模式,输入值设为一个非零值。

若设为阻塞模式,输入值设为0。

WSAAsyncSelect( )或WSAEventSelect( )会将套接字自动设为非阻塞模式,并且都无法直接使用ioctlsocket( )或WSAIoctl()重新设置为阻塞模式。要想将套接字改回阻塞模式,首先必须禁止WSAAsyncSelect( )或WSAEventSelect( ),具体做法是调用WSAAsyncSelect(),同时令其lEvent参数等于0。或者调用WSAEventSelect( ),同时令其lNetworkEvents参数等于0。

1.2.2 FIONREAD

函数
输入
输出
Winsock
说明
两者均可

unsigned long
1+
返回准备在套接字上读取的数据量
若套接字类型为SOCK_STREAM,返回的是在单独一次接收调用中可读取的数据总量。

若套接字类型为SOCK_DGRAM,返回的是在套接字上排队的第一条消息的大小。

1.2.3 SIOCATMARK

函数
输入
输出
Winsock
说明
两者均可

bool
1+
判断是否准备读取带外数据
如果设置MSG_OOB标志调用一个接收函数,而且已经使用setsockopt( )设置SO_OOBINLINE为内嵌方式读取OOB数据,那么就会返回一个布尔值指出接下来是否准备接收OOB数据。

1.2.4 其他I/O控制选项(Winsock2特有)

1.2.4.1 SIO_ENABLE_CIRCULAR-QUEUEING

函数
输入
输出
说明
WSAIoctl
bool
bool
若接收缓冲区队列溢出,则首先丢弃最早收到的消息
只适用于面向消息的套接字
默认情况下,若接收缓冲区满了,以后新收到的消息会被丢弃。

1.2.4.2 SIO_FIND_ROUTE

函数
输入
输出
说明
WSAIoctl
SOCKADDR
bool
验证到指定地址的路由是否存在

1.2.4.3 SIO_FLUSH

函数
输入
输出
说明
WSAIoct1


清除发送队列的内容

1.2.4.4 SIO_BROADCAST_ADDRESS

函数
输入
输出
说明
WSAIoctl

SOCKADDR
返回一个广播地址,可在sendto或WSASendTo中使用

1.2.4.5 SIO_CHK_QOS

函数
输入
输出
说明
WSAIoctl

DWORD
返回套接字的QoS状态
用来检查QoS的六种状态,以下六个标志分别对应于六种不同的状态:

ALLOWED_TO_SEND_DATA

ALLOWED_TO_SEND_DATA用在QoS等级建立好之后(使用SIO_SET_QOS建立),但又没有收到任何RSVP预约请求(RESV)消息之前。若收到一条RESV消息,意味着请求的带宽已经分配给套接字。在收到RESV消息之前,对套接字的数据只会提供Best-Effort的服务。

利用ALLOWED_TO_SEND_DATA标志,可以查询Best-Effort的服务是否足够保证由SIO_SET_QOS请求的QoS服务等级。如果返回1,意味着Best-Effort已经足够使用;如果返回0,意味着Best-Effort尚不足以保证请求的服务等级。若ALLOWED_TO_SEND_DATA标志的返回值是0,那么作为发送方的应用程序,应在发出数据之前,等候一条RESV消息的抵达。

ABLE_TO_RECV_RSVP

ABLE_TO_RECV_RSVP指出主机是否能够在套接字绑定的接口上接收与处理RSVP消息。

LINE_RATE

LINE_RATE返回Best-Effort能使通信速率达到多少,单位是kbit/s。

若线路的通信速率未知,便返回INFO_NOT_AVAIABLE。

LOCAL_TRAFFIC_CONTROL 判断本地主机是否安装通信控制组件,是否能够使用

LOCAL_QOSABILITY 判断本地主机是否支持QoS

END_TO_END_QOSABILITY 判断整个本地网络是否支持QoS

若返回1,表明对应的功能是支持的;

若返回0,表明不支持;

若返回INFO_NOT_AVAIABLE,表明没有办法检查。

1.2.4.6 SIO_GET_QOS

函数
输入
输出
说明
WSAIoctl

QOS
返回套接字的QOS

1.2.4.7 SIO_SET_QOS

函数
输入
输出
说明
WSAIoctl
QOS

设置套接字的QOS

1.2.4.8 SIO_MULTIPOINT_LOOPBACK

函数
输入
输出
说明
WSAIoctl
bool
bool
设置或查询多播数据是否返回套接字
发送多播数据时,当套接字也属于目标多播组的一名成员时,默认行为是多播数据返回套接字。

1.2.4.9 SIO_MULTICAST_SCOPE

函数
输入
输出
说明
WSAIoctl
int
int
设置或获取多播数据的TTL

1.2.4.10 SIO_KEEPLIVE_VALS

函数
输入
输出
说明
WSAIoctl
tcp_keepalive
tcp_keepalive
设置keepalive消息的发送周期
套接字选项SO_KEEPALIVE也允许发送keepalive消息,但其发送间隔时间是在注册表里设定的。若更改了注册表的值,同时也会更改机器上所有进程的keepalive周期。

但使用SIO_KEEPLIVE_VALS便可针对每一个套接字设置keepalive消息发送周期。

structtcp_keepalive

{

u_long onoff;

u_long keepalivetime;

u_long keepaliveinterval;

};

keepalivetime和keepaliveinterval的单位都是毫秒。其中,keepaliveinterval指定发送keepalive消息的间隔时间,直至收到一个响应;keepalivetime用于控制keepalive数据包的发送频率,以查验一个连接是否仍然有效。

1.2.4.11 SIO_RCVALL

函数
输入
输出
说明
WSAIoctl
bool

如果设为TRUE,接收网络上的所有数据包
套接字的地址家族必须是AF_INET;

套接字的类型必须是SOCK_RAW;

套接字的协议必须是IPPROTO_IP;

套接字必须同一个明确的本地接口建立绑定关系,也就是说不可将其绑定到INADDR_ANY。

1.2.4.12 SIO_RCVALL_MCAST

函数
输入
输出
说明
WSAIoctl
unsigned int

接收网络上的所有多播数据包
套接字的地址家族必须是AF_INET;

套接字的类型必须是SOCK_RAW;

套接字的协议必须是IPPROTO_IGMP;

套接字必须同一个明确的本地接口建立绑定关系,也就是说不可将其绑定到INADDR_ANY。

1.2.4.13 SIO_RCVALL_IGMPMCAST

函数
输入
输出
说明
WSAIoctl
unsigned int

接收网络上的所有IGMP数据包
套接字的地址家族必须是AF_INET;

套接字的类型必须是SOCK_RAW;

套接字的协议必须是IPPROTO_IGMP;

套接字必须同一个明确的本地接口建立绑定关系,也就是说不可将其绑定到INADDR_ANY。

1.2.4.14 SIO_ROUTING_INTERFACE_QUERY

函数
输入
输出
说明
WSAIoctl
SOCKADDR
SOCKADDR[ ]
返回向指定地址发送数据的本地接口的地址。
输入的地址可以是单播地址,也可以是多播地址。输出的地址可以在后续的bind( )中使用。

1.2.4.15 SIO_ROUTING_INTERFACE_CHANGE

函数
输入
输出
说明
WSAIoctl
SOCKADDR

与指定地址连接的本地接口发生改变后,发出通知
如果套接字处在阻塞模式,只有接口发生变化后,WSAIoctl( )才会完成并返回。

若套接字处在非阻塞模式,便会返回WSAEWOULDBLOCK错误。随后,应用程序可通过WSAEventSelect( )或WSAAsyncSelect(),等候FD_ROUTING_INTERFACE_CHANGE事件的发生。

输入SOCKADDR结构中指定的地址可以是一个具体的地址,亦可使用INADDR_ANY,表明发生任何路由更改,都发出通知。

1.2.4.16 SIO_ADDRESS_LIST_QUERY

函数
输入
输出
说明
WSAIoctl

SOCKET_ADDRESS_LIST
返回与套接字协议家族相符的本地接口列表
用于取得与套接字协议家族相符的一系列本地传送地址的列表,应用程序可与之建立绑定关系。此时的输出缓冲区是一个SOCKET_ADDRESS_LIST结构,定义如下:

typedefstruct _SOCKET_ADDRESS

{

LPSOCKADDR lpSockaddr;

INT iSockaddrLength;

}SOCKET_ADDRESS;

typedefstruct _SOCKET_ADDRESS_LIST

{

INT iAddressCount;

SOCKET_ADDRESS Address[1];

}SOCKET_ADDRESS_LIST;

其中,iAddressCount字段用于返回列表中地址结构的数量,而Address字段对应的是一个数组,包含了与协议家族相符的一系列地址。

1.2.4.17 SIO_ADDRESS_LIST_CHANGE

函数
输入
输出
说明
WSAIoctl


套接字协议家族的本地接口列表发生变化,
发出通知
如果套接字处于阻塞模式,只有接口列表发生变化后,WSAIoctl( )才会完成并返回。

若套接字处于非阻塞模式,则返回WSAEWOULDBLOCK错误。随后,应用程序可利用WSAEventSelect( )或者WSAAsyncSelect(),等候FD_ADDRESS_LIST_CHANGE事件的发生。

1.2.4.18 SIO_GET_INTERFACE_LIST

函数
输入
输出
说明
WSAIoctl

INTERFACE_INFO[]
返回本地接口列表
typedefunion

{

struct sockaddr Address;

struct sockaddr_in AddressIn;

struct sockaddr_in6_old AddressIn6;

}sockaddr_gen;

typedefstruct _INTERFACE_INFO

{

u_long iiFlags;

sockaddr_gen iiAddress;

sockaddr_gen iiBroadcastAddress;

sockaddr_gen iiNetmask;

}INTERFACE_INFO, FAR * LPINTERFACE_INFO;

iiFlags用于描述接口状态:

IFF_UP;IFF_BROADCAST;IFF_LOOPBACK;IFF_POINTTOPOINT;IFF_MULTICAST

iiAddress是接口的地址。

iiBroadcastAddress是接口对应的广播地址或点对点链路的对端地址。

iiNetmask是接口使用的网络掩码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: