网络编程(基于winsocket)-- 常用函数介绍(二)

来源:互联网 发布:excel数据分析占比 编辑:程序博客网 时间:2024/06/13 11:55

此篇文章继续记录winsocket的常用函数

1、套接字选项

选项影响套接字的操作。获取和设置调节自选项的函数分别是getsockopt()和setsockopt()。

(1)setsockopt()

intWSAAPIsetsockopt(_In_ SOCKET s,_In_ int level,_In_ int optname,_In_reads_bytes_opt_(optlen) const char FAR * optval,_In_ int optlen);

参数s:指示套接字句柄;

参数level:指定此选项被定义在哪个级别,如SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP等;

参数optname:声明套接字选项的名称;

参数optval:指定一个缓冲区,存储所请求或定义的选项值;

参数optlen:指定参数optval所指的缓冲区的大小

如果函数成功,则返回0,否则返回SOCKET_ERROR。

OSI网络分层结构对应参数level的不同级别:


应用层:参数level设置为SOL_SOCKET,是对套接字自身的一些参数的配置;

传输层:协议为TCP、UDP,参数level设置为IPPROTO_TCP、IPPROTO_UDP;

网络层:参数level设置为IPPROTO_IP。



具体使用如下: 
 
1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: 
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.同上在recv()完成上述功能(默认情况是将socket缓冲区的内容拷贝到系统缓冲区): 
int nZero = 0;setsockopt(socket,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;则功能和2.)作用相同;   m_sLinger.l_linger = 5; //(容许逗留的时间为5秒)   setsockopt(s, SOL_SOCKET, SO_LINGER, (const char*)&m_sLinger, sizeof(linger));


(2)getsockopt()
intWSAAPIgetsockopt(_In_ SOCKET s,_In_ int level,_In_ int optname,_Out_writes_bytes_(*optlen) char FAR * optval,_Inout_ int FAR * optlen);

此函数用于取得socket套接字的操作选项值,例:

int nNetTimeout;//时间//发送时限 getsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int)); //函数会在nNetTimeout返回设置的时间


2、I/O控制命令

I/O控制命令(缩写为ioctl)用来控制套接字上I/O的行为,也可以用来获取套接字上未决的I/O信息。向套接字发送I/O控制命令的函数有两个:winsock1.1:ioctlsocket();winsock2:WSAIoctl()。

(1)ioctlsocket()

ioctlsocket()函数可以控制套接字的I/O模式

intWSAAPIioctlsocket(    _In_ SOCKET s,    _In_ long cmd,    _Inout_ u_long FAR * argp    );
参数s:是一个套接字句柄

参数cmd:指示在套接字上要执行的命令

参数argp:指向套接字参数的指针

(2)WSAIoctl()

此函数是winsock2新引进的I/O控制命令函数,它增加了一些输入参数,同时还增加了一些输入参数用来从调用中返回数据。另外,该函数还可以使用重叠I/O。

intWSAAPIWSAIoctl(    _In_ SOCKET s,    _In_ DWORD dwIoControlCode,    _In_reads_bytes_opt_(cbInBuffer) LPVOID lpvInBuffer,    _In_ DWORD cbInBuffer,    _Out_writes_bytes_to_opt_(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer,    _In_ DWORD cbOutBuffer,    _Out_ LPDWORD lpcbBytesReturned,    _Inout_opt_ LPWSAOVERLAPPED lpOverlapped,    _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine    );


参数s:是一个套接字句柄

参数dwIoControlCode:描述将进行的操作控制代码,在设置接收全部选项时使用SIO_RCVALL

参数lpvInBuffer:指向输入缓冲区的地址

参数cbInBuffer:指向输入缓冲区的大小

参数lpvOutBuffer:指向输出缓冲区的地址

参数cbOutBuffer:指向输出缓冲区的大小

参数IpcbBytesReturned:是一个输出参数,返回输出实际字节数的地址

参数IpOverlapped:指向WSAOVERLAPPED的结构的地址

参数IpCompletionRoutine:指向操作结束后调用的例程指针

注:最后两个参数在重叠I/O时才会使用。



示例:

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









原创粉丝点击