socket网络编程中设置socket选项的ioctlsocket、setsockopt和WSAIoctl函数的使用(附源码)

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html       在socket编程中,我们时常要设置socket套接字相关选项,设置不同的选项要调用的函数可能是不一样的,比如ioctlsocket、setsockopt和WSAIoctl函数。这三个函数很容易混淆,今天我们就来讲讲这几个函数主要是用来设置哪些选项的。

1、ioctrlsocket函数

       ioctlsocket函数主要是用来设置或取消非阻塞套接字的。将套接字设置为非阻塞式套接字后,connect、send和recv等函数将变成非阻塞式的,调用后会立即返回,执行的操作结果成功与否,需要通过后续代码去判断。

       设置非阻塞式套接字的代码如下:

unsigned long unblock = 1;
int ret = ioctlsocket(tSock, FIONBIO, (unsigned long *)&unblock);

2、setsockopt函数

       setsockopt可以用来设置套接字的一系列选项,最常用的是用来设置接收缓冲区和发送缓冲区大小的,如下所示:

// 设置发送缓冲区大小
int optVal = 2*1024*1024; // 2MB
setsockopt(tSock, SOL_SOCKET, SO_SNDBUF, (char *)&optVal, sizeof(optVal));

// 设置接收缓冲区大小
optVal = 2*1024*1024; // 2MB
setsockopt(tSock, SOL_SOCKET, SO_RCVBUF, (char *)&optVal, sizeof(optVal));

3、WSAIoctl函数

       WSAIoctl则主要用来设置TCP连接的心跳参数的,这个心跳参数是属于TCPIP协议栈中的。设置的心跳参数对应如下的结构体:

/* Argument structure for SIO_KEEPALIVE_VALS */
struct tcp_keepalive {
    u_long  onoff;
    u_long  keepalivetime;
    u_long  keepaliveinterval;
};
 

       其中,keepalivetime 成员用来指定在发送第一个 keep-alive 数据包后到发送下个keep-alive 数据包之间的间隔时间(以毫秒为单位)keepaliveinterval 成员用来指定当发送keep-alive 数据包后未收到确认消息超时时发送连续 keep-alive 数据包之间的间隔(以毫秒为单位)

       在设置心跳参数之前,要先调用setsockopt打开心跳包设置选项。相关代码如下所示:

// 先调用setsockopt打开发送心跳包(设置)选项
int optval = 1;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&optval, optlen) < 0)
	return 1;

// 设置心跳参数
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.keepalivetime = 10*1000;
alive.keepaliveinterval = 10*1000;
 
DWORD dwBytesRet;
WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, &dwBytesRet, NULL, NULL))

       有人可能会说,不是还有个心跳包探测次数的设置参数吗?上述结构体tcp_keepalive中并没有这个参数,那是因为Windows操作系统中的心跳探测次数是固定为10次,是不可修改的。Linux系统中是可以修改的。

       关于TCPIP协议栈的心跳、丢包重传、连接超时机制以及实例详解,可以查看我的文章:

TCPIP协议栈的心跳、丢包重传、连接超时机制实例详解(附源码)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/121637018

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
///////////////////////////////////////////////////////////////// // 初始化Socket bool CIOCPModel::_InitializeListenSocket() { // AcceptEx 和 GetAcceptExSockaddrs 的GUID,用于导出函数指针 GUID GuidAcceptEx = WSAID_ACCEPTEX; GUID GuidGetAcceptExSockAddrs = WSAID_GETACCEPTEXSOCKADDRS; // 服务器地址信息,用于绑定Socket struct sockaddr_in ServerAddress; // 生成用于监听的Socket的信息 m_pListenContext = new PER_SOCKET_CONTEXT; // 需要使用重叠IO,必须得使用WSASocket来建立Socket,才可以支持重叠IO操作 m_pListenContext->m_Socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == m_pListenContext->m_Socket) { this->_ShowMessage("初始化Socket失败,错误代码: %d.\n", WSAGetLastError()); return false; } else { TRACE("WSASocket() 完成.\n"); } // 将Listen Socket绑定至完成端口 if( NULL== CreateIoCompletionPort( (HANDLE)m_pListenContext->m_Socket, m_hIOCompletionPort,(DWORD)m_pListenContext, 0)) { this->_ShowMessage("绑定 Listen Socket至完成端口失败!错误代码: %d/n", WSAGetLastError()); RELEASE_SOCKET( m_pListenContext->m_Socket ); return false; } else { TRACE("Listen Socket绑定完成端口 完成.\n"); } // 填充地址信息 ZeroMemory((char *)&ServerAddress, sizeof(ServerAddress)); ServerAddress.sin_family = AF_INET; // 这里可以绑定任何可用的IP地址,或者绑定一个指定的IP地址 //ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY); ServerAddress.sin_addr.s_addr = inet_addr(m_strIP.GetString()); ServerAddress.sin_port = htons(m_nPort); // 绑定地址和端口 if (SOCKET_ERROR == bind(m_pListenContext->m_Socket, (struct sockaddr *) &ServerAddress, sizeof(ServerAddress))) { this->_ShowMessage("bind()函数执行错误.\n"); return false; } else { TRACE("bind() 完成.\n"); } // 开始进行监听 if (SOCKET_ERROR == listen(m_pListenContext->m_Socket,SOMAXCONN)) { this->_ShowMessage("Listen()函数执行出现错误.\n"); return false; } else { TRACE("Listen() 完成.\n"); } // 使用AcceptEx函数,因为这个是属于WinSock2规范之外的微软另外提供的扩展函数 // 所以需要额外获取一下函数的指针, // 获取AcceptEx函数指针 DWORD dwBytes = 0; if(SOCKET_ERROR == WSAIoctl

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dvlinker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值