windows下设置socket的connect超时
变相的实现connect的超时,我要讲的就是这个方法,原理上是这样的: 1.建立socket 2.将该socket设置为非阻塞模式 3.调用connect() 4.使用select()检查该socket描述符是否可写(注意,是可写) 5.根据select()返回的结果判断connect()结果 6.将socket设置为阻塞模式(如果你的程序不需要用阻塞模式的,这步就省了,不过一般情况下都是用阻塞模式的,这样也容易管理) 在Windows环境下进行网络编程时,有时需要对socket连接进行超时控制,特别是在客户端与服务器通信的过程中,如果连接请求长时间没有响应,程序可能会陷入无休止的等待状态,从而导致资源浪费甚至程序卡死。本文将详细介绍一种在Windows系统中设置socket连接超时的方法。 ### 一、基本概念 在讲解如何设置socket连接超时之前,我们先来了解一下几个基本概念: 1. **Socket**:是一种用于进程间通信的机制,通过它可以实现在不同计算机或者同一台计算机上的进程之间的数据交换。 2. **阻塞模式与非阻塞模式**:在阻塞模式下,当一个线程执行到socket操作时,如果该操作未能立即完成,则线程会被阻塞直到操作完成。而非阻塞模式下,即使操作未能立即完成,线程也不会被阻塞,而是立即返回一个错误码或特定值。 3. **Connect函数**:用于建立客户端与服务器之间的连接。在客户端程序中,connect函数会尝试与指定的服务器地址建立连接。 4. **Select函数**:用于检测一个或多个套接字的活动状态,即是否有数据可以读取、写入或发生错误等。 ### 二、实现步骤 接下来,我们将根据给定的描述中的六个步骤,逐一解析如何在Windows环境下设置socket连接超时。 #### 1. 建立socket ```c SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ``` 通过`socket`函数创建一个socket对象,这里指定了使用TCP协议。 #### 2. 设置socket为非阻塞模式 ```c unsigned long ul = 1; ioctlsocket(sockfd, FIONBIO, &ul); ``` 使用`ioctlsocket`函数将socket设置为非阻塞模式。这一步非常重要,因为在非阻塞模式下,当connect调用不能立即完成时,不会阻塞当前线程。 #### 3. 调用connect() ```c struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(strIP); serv_addr.sin_port = htons(nPort); if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) { // 处理连接失败的情况 } ``` 调用`connect`函数尝试建立连接。如果服务器端未准备好接收连接,connect函数会返回-1,并且设置errno为EINPROGRESS,表示连接正在建立过程中。 #### 4. 使用select()检查socket描述符是否可写 ```c timeval tm; tm.tv_sec = 3; tm.tv_usec = 0; FD_ZERO(&set); FD_SET(sockfd, &set); if (select(sockfd + 1, NULL, &set, NULL, &tm) > 0) { // 连接已经建立成功 } ``` 使用`select`函数检测socket是否可写。如果在设定的时间内连接成功,那么select函数会返回一个大于0的值,表示该socket可写;如果返回0,则表示超时;如果返回-1则表示出错。 #### 5. 根据select()返回的结果判断connect()结果 ```c int error = -1; int len = sizeof(int); getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, /*(socklen_t*)*/ &len); if (error == 0) ret = true; else ret = false; ``` 使用`getsockopt`函数获取socket的状态,通过SO_ERROR选项来检查connect是否成功。如果error等于0,表示连接成功。 #### 6. 将socket设置为阻塞模式 ```c ul = 0; ioctlsocket(sockfd, FIONBIO, &ul); ``` 如果后续的操作需要使用阻塞模式,可以通过再次调用`ioctlsocket`将socket设置回阻塞模式。 ### 三、示例代码分析 在给定的部分内容中,提供了两种实现方式:一种是直接使用`connect`函数进行连接,另一种则是使用`select`函数实现超时控制。其中第二种方法实现了题目所要求的超时设置功能,更符合实际应用需求。 ### 四、总结 通过以上介绍,我们可以看到在Windows环境下设置socket连接超时的主要步骤包括:建立socket、设置非阻塞模式、调用connect、使用select检测socket状态、判断connect结果以及最后将socket恢复为阻塞模式。这些步骤有效地帮助开发者在进行网络编程时避免因长时间等待而导致的问题,提高了程序的健壮性和用户体验。
void TcpConnect(char* strIP, UINT nPort)
{
struct sockaddr_in serverAddress;
SOCKET hSocket = NULL;
hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if( hSocket==INVALID_SOCKET)
{
return;
}
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(strIP);
serverAddress.sin_port = htons((short)nPort);
int iTimeOut = 3000;
setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&iTimeOut,sizeof(iTimeOut));
setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&iTimeOut,sizeof(iTimeOut));
if( SOCKET_ERROR==connect(hSocket, (sockaddr*)&serverAddress, sizeof(serverAddress)) )
{
closesocket(hSocket);
DWORD gle = WSAGetLastError();
return;
}
char buff[] = "hello";
int sl=::send(hSocket,(char*)buff, sizeof(buff), 0);
- 粉丝: 0
- 资源: 18
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Spring Boot框架的博客系统.zip
- (源码)基于Spring Boot框架的博客管理系统.zip
- (源码)基于ESP8266和Blynk的IR设备控制系统.zip
- (源码)基于Java和JSP的校园论坛系统.zip
- (源码)基于ROS Kinetic框架的AGV激光雷达导航与SLAM系统.zip
- (源码)基于PythonDjango框架的资产管理系统.zip
- (源码)基于计算机系统原理与Arduino技术的学习平台.zip
- (源码)基于SSM框架的大学消息通知系统服务端.zip
- (源码)基于Java Servlet的学生信息管理系统.zip
- (源码)基于Qt和AVR的FestosMechatronics系统终端.zip
- 1
- 2
- 3
- 4
前往页