SETSOCKOPT IOCTLSOCKET 设置非阻塞SOCKET函数

1,ioctlsocket()算法

#include <winsock.h>服务器

 

This function controls the I/O mode of a socket.网络

int ioctlsocket(
  SOCKET s,
  long cmd,
  u_long FAR* argp
);

 

Parameters

 

  • s异步

  • [in] Descriptor identifying a socket.socket

  • cmdide

  • [in] Command to perform on socket s.函数

  • argp性能

  • [in, out] Pointer to a parameter for cmd.this

 

Return Values

 

If no error occurs, this function returns zero. If an error occurs, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.spa

 

The following table shows a list of possible error codes.

 

 

u_long mode = 0;
ioctlsocket(s,FIONBIO,&mode);
控制为阻塞方式。

u_long mode = 1;
ioctlsocket(s,FIONBIO,&mode);
控制为非阻塞方式。 

本函数可用于任一状态的任一套接口。它用于获取与套接口相关的操做参数,而与具体协议或通信子系统无关。支持下列命令:
  FIONBIO:容许或禁止套接口s的非阻塞模式。argp指向一个无符号长整型。如容许非阻塞模式则非零,如禁止非阻塞模式则为零。当建立一个套接口时,它就处于阻塞模式(也就是说非阻塞模式被禁止)。这与BSD套接口是一致的。WSAAsynSelect()函数将套接口自动设置为非阻塞模式。若是已对一个套接口进行了WSAAsynSelect() 操做,则任何用ioctlsocket()来把套接口从新设置成阻塞模式的试图将以WSAEINVAL失败。为了把套接口从新设置成阻塞模式,应用程序必须首先用WSAAsynSelect()调用(IEvent参数置为0)来禁至WSAAsynSelect()。


  FIONREAD:肯定套接口s自动读入的数据量。argp指向一个无符号长整型,其中存有ioctlsocket()的返回值。若是s是SOCKET_STREAM类型,则FIONREAD返回在一次recv()中所接收的全部数据量。这一般与套接口中排队的数据总量相同。若是S是SOCK_DGRAM 型,则FIONREAD返回套接口上排队的第一个数据报大小。

 


  SIOCATMARK:确实是否全部的带外数据都已被读入。这个命令仅适用于SOCK_STREAM类型的套接口,且该套接口已被设置为能够在线接收带外数据(SO_OOBINLINE)。如无带外数据等待读入,则该操做返回TRUE真。不然的话返回FALSE假,下一个recv()或recvfrom()操做将检索“标记”前一些或全部数据。应用程序可用SIOCATMARK操做来肯定是否有数据剩下。若是在“紧急”(带外)数据前有常规数据,则按序接收这些数据(请注意,recv()和recvfrom()操做不会在一次调用中混淆常规数据与带外数据)。argp指向一个BOOL型数,ioctlsocket()在其中存入返回值。

 

2,setsockopt()  简述:

 

Call this member function to set a socket option.

BOOL SetSockOpt(
   int nOptionName,
   const void* lpOptionValue,
   int nOptionLen,
   int nLevel = SOL_SOCKET 
);

Parameters

  • nOptionName

  • The socket option for which the value is to be set.

  • lpOptionValue

  • A pointer to the buffer in which the value for the requested option is supplied.

  • nOptionLen

  • The size of the lpOptionValue buffer in bytes.

  • nLevel

  • The level at which the option is defined; the only supported levels are SOL_SOCKET and IPPROTO_TCP.

setsockopt()  简述:  设置套接口的选项。  #include <winsock.h>  int PASCAL FAR setsockopt( SOCKET s, int level, int optname,  const char FAR* optval, int optlen);  s:标识一个套接口的描述字。  level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。  optname:需设置的选项。  optval:指针,指向存放选项值的缓冲区。  optlen:optval缓冲区的长度。  注释:  setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不一样协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操做,诸如加急数据是否在普通数据流中接收,广播数据是否能够从套接口发送等等。  有两种套接口的选项:一种是布尔型选项,容许或禁止一种特性;另外一种是整形或结构选项。容许一个布尔型选项,则将optval指向非零整形数;禁止一个选项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其余选项,optval指向包含所需选项的整形数或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述状况的行动:套接口上有排队的待发送数据,且closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。应用程序经过建立一个linger结构来设置相应的操做特性:  struct linger {  int l_onoff;  int l_linger;  };  为了容许SO_LINGER,应用程序应将l_onoff设为非零,将l_linger设为零或须要的超时值(以秒为单位),而后调用setsockopt()。为了容许SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff应设为零,而后调用setsockopt()。  缺省条件下,一个套接口不能与一个已在使用中的本地地址捆绑(参见bind())。但有时会须要“重用”地址。由于每个链接都由本地地址和远端地址的组合惟一肯定,因此只要远端地址不一样,两个套接口与一个地址捆绑并没有大碍。为了通知WINDOWS套接口实现不要由于一个地址已被一个套接口使用就不让它与另外一个套接口捆绑,应用程序可在bind()调用前先设置SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释;故此无需(但也无害)将一个不会共用地址的套接口设置该选项,或者在bind()对这个或其余套接口无影响状况下设置或清除这一选项。  一个应用程序能够经过打开SO_KEEPALIVE选项,使得WINDOWS套接口实如今TCP链接状况下容许使用“保持活动”包。一个WINDOWS套接口实现并非必需支持“保持活动”,可是若是支持的话,具体的语义将与实现有关,应遵照RFC1122“Internet主机要求-通信层”中第4.2.3.6节的规范。若是有关链接因为“保持活动”而失效,则进行中的任何对该套接口的调用都将以WSAENETRESET错误返回,后续的任何调用将以WSAENOTCONN错误返回。  TCP_NODELAY选项禁止Nagle算法。Nagle算法经过将未确认的数据存入缓冲区直到蓄足一个包一块儿发送的方法,来减小主机发送的零碎小数据包的数目。但对于某些应用来讲,这种算法将下降系统性能。因此TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在确切了解它的效果并确实须要的状况下,才设置TCP_NODELAY选项,由于设置后对网络性能有明显的负面影响。TCP_NODELAY是惟一使用IPPROTO_TCP层的选项,其余全部选项都使用SOL_SOCKET层。  若是设置了SO_DEBUG选项,WINDOWS套接口供应商被鼓励(但不是必需)提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨论范围。  setsockopt()支持下列选项。其中“类型”代表optval所指数据的类型。  选项 类型 意义  SO_BROADCAST BOOL 容许套接口传送广播信息。  SO_DEBUG BOOL 记录调试信息。  SO_DONTLINER BOOL 不要由于数据未发送就阻塞关闭操做。设置本选项至关于将SO_LINGER的l_onoff元素置为零。  SO_DONTROUTE BOOL 禁止选径;直接传送。  SO_KEEPALIVE BOOL 发送“保持活动”包。  SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。  SO_OOBINLINE BOOL 在常规数据流中接收带外数据。  SO_RCVBUF int 为接收肯定缓冲区大小。  SO_REUSEADDR BOOL 容许套接口和一个已在使用中的地址捆绑(参见bind())。  SO_SNDBUF int 指定发送缓冲区大小。  TCP_NODELAY BOOL 禁止发送合并的Nagle算法。  setsockopt()不支持的BSD选项有:  选项名 类型 意义  SO_ACCEPTCONN BOOL 套接口在监听。  SO_ERROR int 获取错误状态并清除。  SO_RCVLOWAT int 接收低级水印。  SO_RCVTIMEO int 接收超时。  SO_SNDLOWAT int 发送低级水印。  SO_SNDTIMEO int 发送超时。  SO_TYPE int 套接口类型。  IP_OPTIONS 在IP头中设置选项。  返回值:  若无错误发生,setsockopt()返回0。不然的话,返回SOCKET_ERROR错误,应用程序可经过WSAGetLastError()获取相应错误代码。  错误代码:  WSANOTINITIALISED:在使用此API以前应首先成功地调用WSAStartup()。  WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。  WSAEFAULT:optval不是进程地址空间中的一个有效部分。  WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。  WSAEINVAL:level值非法,或optval中的信息非法。  WSAENETRESET:当SO_KEEPALIVE设置后链接超时。  WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM类型的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。  WSAENOTCONN:当设置SO_KEEPALIVE后链接被复位。  WSAENOTSOCK:描述字不是一个套接口。  用法  1.设置调用closesocket()后,仍可继续重用该socket。调用closesocket()通常不会当即关闭socket,而经历TIME_WAIT的过程。  BOOL bReuseaddr = TRUE;  setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( const char* )&bReuseaddr, sizeof( BOOL ) );  2. 若是要已经处于链接状态的soket在调用closesocket()后强制关闭,不经历TIME_WAIT的过程:  BOOL bDontLinger = FALSE;  setsockopt( s, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof( BOOL ) );  3.在send(),recv()过程当中有时因为网络情况等缘由,收发不能预期进行,能够设置收发时限:  int nNetTimeout = 1000; //1秒  //发送时限  setsockopt( socket, SOL_S0CKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof( int ) );  //接收时限  setsockopt( socket, SOL_S0CKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) );  4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节(异步);系统默认的状态发送和接收一次为8688字节(约  为8.5K);在实际的过程当中若是发送或是接收的数据量比较大,能够设置socket缓冲区,避免send(),recv()不断的循环收发:  // 接收缓冲区  int nRecvBuf = 32 * 1024; //设置为32K  setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( const char* )&nRecvBuf, sizeof( int ) );  //发送缓冲区  int nSendBuf = 32*1024; //设置为32K  setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBuf, sizeof( int ) );  5.在发送数据的时,不执行由系统缓冲区到socket缓冲区的拷贝,以提升程序的性能:  int nZero = 0;  setsockopt( socket, SOL_S0CKET, SO_SNDBUF, ( char * )&nZero, sizeof( nZero ) );  6.在接收数据时,不执行将socket缓冲区的内容拷贝到系统缓冲区:  int nZero = 0;  setsockopt( s, SOL_S0CKET, SO_RCVBUF, ( char * )&nZero, sizeof( int ) );  7.通常在发送UDP数据报的时候,但愿该socket发送的数据具备广播特性:  BOOL bBroadcast = TRUE;  setsockopt( s, SOL_SOCKET, SO_BROADCAST, ( const char* )&bBroadcast, sizeof( BOOL ) );  8.在client链接服务器过程当中,若是处于非阻塞模式下的socket在connect()的过程当中能够设置connect()延时,直到accpet()被调用(此设置只  有在非阻塞的过程当中有显著的做用,在阻塞的函数调用中做用不大)  BOOL bConditionalAccept = TRUE;  setsockopt( s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, ( const char* )&bConditionalAccept, sizeof( BOOL ) );  9.若是在发送数据的过程当中send()没有完成,还有数据没发送,而调用了closesocket(),之前通常采起的措施是shutdown(s,SD_BOTH),可是数  据将会丢失。  某些具体程序要求待未发送完的数据发送出去后再关闭socket,可经过设置让程序知足要求:  struct linger {  u_short l_onoff;  u_short l_linger;  };  linger m_sLinger;  m_sLinger.l_onoff = 1; //在调用closesocket()时还有数据未发送完,容许等待  // 若m_sLinger.l_onoff=0;则调用closesocket()后强制关闭  m_sLinger.l_linger = 5; //设置等待时间为5秒  setsockopt( s, SOL_SOCKET, SO_LINGER, ( const char* )&m_sLinger, sizeof( linger ) );

相关文章
相关标签/搜索