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

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

1、套接字选项

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

(1)setsockopt()

int
WSAAPI
setsockopt(
	_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()
int
WSAAPI
getsockopt(
	_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模式

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

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

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

(2)WSAIoctl()

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

int
WSAAPI
WSAIoctl(
    _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); //控制为非阻塞方式









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值