Linux 下socket超时(connect超时/recv超时)

socket连接(connect函数)超时 最近做一个分布式的课题,在测试的时候发现当并发度超过某个值的时候connect()函数就会超时。第一直觉是文件描述符的数量超过了某些系统限制,于是上网查各种方法扩大文件描述符上限。过程很痛苦,因为我其实并不在乎这些实现上的细节,我只是想完成算法的测试而已。于是又上网查与队列相关的关键词,还是没结果。最后我灵光一现,如果真的是因为队列被撑破,那我也不用非要扩大队列,我放慢填充队列的时间,给消费者足够的时间消耗取走队列里的东西不就行了。于是在创立两次链接之间加了个sleep,再测试,果然没有超时了,问题解决。 阅读详情
 

Linux 下socket超时(connect超时/recv超时)



 connect超时:

目前各平台通用的设置socket connect超时的办法是通过select(),具体方法如下:

1.建立socket;

2.将该socket设置为非阻塞模式;

3.调用connect();

4.使用select()检查该socket描述符是否可写;

5.根据select()返回的结果判断connect()结果;

6.将socket设回阻塞模式。

 

下面给出的是我写的client程序(已经编译通过):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <asm/ioctls.h>
 
#define MAXDATASIZE 4926

int detect_imap(const char *server ,char *protocol,unsigned short port)
{
    int sockfd,numbytes;
    char buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in their_addr;

    if ((he = gethostbyname(server)) == NULL)
    {
        herror("gethostbyname");
        return 0; 
    } 
    
    if ((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
        perror("socket");
        return 0;
    }
    
    unsigned long ul=1;
    int rm=ioctl(sockfd,FIONBIO,&ul); 
    if(rm==-1)
    {
      close(sockfd); 
      return 0;   
    }
    
    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(port);
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);
   
    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == 0)
    {
     printf("connected/n");
    } 
    if(errno!=EINPROGRESS) 
    {
     perror("connect");
      printf("cannot connect:%s/n",server);
      return 0;
    }     
 
    struct timeval timeout; 
    fd_set r;          
    FD_ZERO(&r);
    FD_SET(sockfd,&r); 
    timeout.tv_sec=0;    
    timeout.tv_usec=100;
    int retval = select(sockfd+1,NULL,&r,NULL,&timeout);
    if(retval==-1)
    {
      perror("select");
      return 0;
    }
    else if(retval == 0)
    {
      fprintf(stderr,"timeout/n");
      return 0;
    }
    printf("%sconnected/n",server);

    unsigned long ul1=0;
    rm=ioctl(sockfd,FIONBIO,(unsigned long*)&ul1); 
    if(rm==-1)
    {
      close(sockfd);
      return 0;      
    }
  
    if ((numbytes=recv(sockfd,buf,MAXDATASIZE,0)) == -1)
    {
      perror("recv");
      return 0; 
    }
    
    buf[numbytes] = '/0';
    if (0 == strncmp(buf,"* OK",4))
    {
      printf("Received: %s",buf);
      close(sockfd);
      return 1;
    }
    else
    {
      printf("Error protocol!");
      close(sockfd);
      return 0;  
    }
}

int 
main(int argc,char *argv[])
{
   int i;
   if (argc!=2)
    {
       fprintf(stderr,"usage:client hostname/n");
       exit(1);
    }

   i = detect_imap(argv[1] ,argv[2],143);
   printf ("%d",i);
}

 

 

以上代码工作的很好,并且也可以通过getsockopt()获得连接发生错误的确切信息,但这总方法难免觉得有些复杂,因为要涉及到阻塞状态的解除和回置。

这里有个简单的操作方法,同样可以设置连接超时:即通过SO_SNDTIMO套节字参数让超时操作跳过select。

原因是:Linux内核源码中connect的超时参数和SO_SNDTIMO操作的参数一致。

因此,在linux平台下,可以通过connect之前设置SO_SNDTIMO来达到控制连接超时的目的。

部分修正代码如下:

    struct timeval timeo;
    socklen_t len = sizeof(timeo);
    timeo.tv_sec = overtime;


     if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1)
    {
        strcpy(reason,strerror(errno));
        perror("setsockopt");
       return 0;
    }
    
    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(serverStruct->port);
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);
  
    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
    {  
      if (errno == EINPROGRESS) 
       {
          strcpy(reason,"timeout");
          return 0;
        }  
       strcpy(reason,strerror(errno));
       perror("connect");
        return 0;
    }  

 

编译运行:gcc client_select.c -o client_select

                    ./client_select imap.21cn.com

ps:列子是对imap协议进行分析时的代码。

 

recv超时:

如果要设置接收超时,可以用setsockopt()和send超时一样,只需将如下代码添加在connect之后就可以了。

 timeout.tv_sec=0;    
    timeout.tv_usec=500;
    int result = setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout.tv_sec,sizeof(struct timeval));
    if (result < 0)
    {
      perror("setsockopt"); 
    }

【异常】原来提示SocketTimeoutException:connect timed out还可能是外部因素导致 原来提示SocketTimeoutException:connect timed out还可能是外部因素导致 阅读详情

相关推荐

配置Linux下DNS服务器connect错误解决办法

配置好DNS正向和反向区域文件后,使用host命令测试报错连接服务器超时!

Socket connect阻塞导致连接超时过长

在项目中,机械臂作为服务端,软件程序编写一个客户端进行连接,connect连接出现有异常时客户端线程阻塞时间过长;

heitong_fu的博客 3090

ISCE2+MintPy环境搭建实战:用Anaconda五分钟搞定InSAR处理全家桶

本文提供了一份详细的ISCE2+MintPy环境安装教程,旨在帮助InSAR处理初学者快速搭建开发环境。通过使用Anaconda创建虚拟环境并配置国内镜像,用户可在五分钟内一键安装ISCE2和MintPy全家桶,有效解决依赖冲突和版本兼容性问题,让用户能专注于数据处理本身。

2y3u4i5o6p的博客 1005

linux下使用write\send发送数据报 EAGAIN : Resource temporarily unavailable 错

http://badqiu.iteye.com/blog/1149965 linux下使用write\send发送数据报 EAGAIN : Resource temporarily unavailable 错 首先是我把套接字设置为异步的了,然后在使用write发送数据时采取的方式是循环发送大量的数据;由于是异步的,write\send将要发送的数据提交到发送缓冲区后是立即返回的,

hanyingzhong的专栏 2万+

SAP VF01开票报错:出口贸易数据不完整

找了半天资料,最后发现是没有维护凭证抬头的数据;由于我不是SD模块顾问,整体流程使用的是原本环境里面的数据,用新建工厂引用,所以也不知道为啥会出发这个贸易业务。正常传到FICO模块,生成会计凭证、获利分析、利润中心及CO凭证。需要维护这三个字段后才能正常转到FI生成会计凭证。VF01开票报错:出口贸易数据不完整。

MaiKouBei的博客 1544

DEAP数据集实战指南:从脑电信号到情绪分类的完整流程解析

本文提供了DEAP数据集在脑电信号情绪识别领域的完整实战指南。详细解析了数据下载、结构理解、频带功率特征提取等核心步骤,并演示了如何构建和评估机器学习分类模型,为研究者实现从原始脑电信号到情绪分类的完整流程提供了清晰路径。

jj890的博客 909

gsoap 超时(timeout)设置

参考:http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc19.19 gsoap就不用介绍了,是一个c/c++编写的可用于服务端与客户端的连接工具。 Socket connect, accept, send, and receive timeout values can be set to manage sock...

weixin_30823227的博客 388

Linux 配置 multipath 多路径

每天一个 DBA 小知识,助你更进一步!

LuciferLiu_DBA 3299

基于TCP的socket编程

面向连接:先 connect/accept 才能 send/recv。Socket:操作系统提供的网络编程接口(文件描述符/句柄)accept() 接受连接 → 得到“已连接socket”TCP:面向连接、可靠、有序、字节流(stream)recv()/send() 收发数据(循环)send()/recv() 收发数据(循环)socket() 创建监听套接字。listen() 进入监听状态。connect() 连接服务器。socket() 创建套接字。close() 关闭。close() 关闭。

航哥的女人最优秀 198

Openclaw第3章:进阶部署

本章面向需要在特定环境中稳定运行 OpenClaw 的用户,介绍 Windows、Linux、Docker 以及 Cloudflare Workers 四种进阶部署方式。每种方式各有侧重:Windows 部署适合桌面用户日常使用,Linux 部署适合开发者,Docker 部署适合追求环境隔离的运维场景,Cloudflare Workers 部署则适合希望获得全球边缘网络加速的用户。读者可根据自身环境和需求选择合适的方案,完成本章后可继续阅读第4章了解维护升级流程。

Maynor的博客 1295

软考中级-软件设计师 知识点整理(一篇就过了 建议收藏)

软考中级-软件设计师上午题知识点总结

片言可决讼,半纸能缚龙 17万+

【Linux Day14 TCP网络通讯】

本文介绍了TCP网络通讯的基本编程流程,包括关键接口函数的使用方法和示例代码。主要内容包括: TCP编程核心接口:socket()创建套接字、bind()绑定地址端口、listen()创建监听队列、accept()处理连接、connect()发起连接、send()/recv()数据收发、close()关闭连接。 示例代码展示了简单的客户端和服务器端实现,客户端通过connect连接服务器并收发数据,服务器通过accept接收连接并处理请求。 服务器端引入多线程处理并发连接,每个客户端连接由独立线程处理,提高

qq_63282188的博客 1174

【30天从零玩转AI应用开发】第16篇:智能体Agent入门——ReAct框架原理+首个会思考、会动手的AI实战

摘要: 本文介绍了AI智能体(Agent)的核心概念及其与普通大模型(LLM)的区别。通过ReAct(Reason+Act)框架,智能体实现了自主思考、调用工具和分步执行的能力。文章详细讲解了LangChain Agent的四大组件,并推荐新手使用ZERO_SHOT_REACT_DESCRIPTION类型。最后提供了一个完整的智能体实战代码示例,该智能体具备数学计算和天气查询功能,能够自主选择工具完成任务,展示了AI从”被动回答“到”主动行动“的关键进化。

在上海谋生的软件喵记录喵生 626

【嵌入式Linux应用开发基础】进程间通信:套接字

在嵌入式Linux应用开发中,套接字广泛应用于网络通信和本地进程间通信。函数将套接字绑定到指定的 IP 地址和端口号,以便客户端能够连接到该服务器。函数接受连接,并返回一个新的套接字描述符,用于与该客户端进行通信。函数在服务器端和客户端之间进行数据的接收和发送。函数开始监听指定端口,等待客户端的连接请求。函数创建一个套接字,指定套接字类型和协议。:用于在已建立的连接上发送和接收数据。TCP + epoll多路复用。:关闭套接字连接,释放资源。函数关闭套接字,释放资源。:通信结束后,关闭套接字。

m0_74824496的博客 36

CPA-7-资产减值

摘要:本文系统梳理了资产减值会计处理规范,涵盖六大要点:1)不同资产适用的减值准则(存货、长期资产、金融资产);2)减值测试触发条件与例外情形(商誉等需年度强制测试);3)存货可变现净值计算方法及特殊考量;4)可收回金额的双重判定标准(公允价值净额与现值孰高);5)资产组认定标准及减值分摊顺序(先商誉后按比例);6)含少数股东商誉的减值测试方法(需调整包含完全商誉的账面价值)。文中通过具体案例演示了合并报表中商誉减值的计算过程,强调比较基准应包含少数股东权益对应的商誉价值。

qq_34047402的博客 204

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Linux网络编程-TCP协议及其编程

本文系统介绍了TCP协议及其编程实现。主要内容包括:1)TCP协议特点:面向连接、可靠传输、流式套接字,通过三次握手建立连接、四次挥手断开连接;2)TCP编程流程;3)TCP机制:通过序列号/确认号、超时重传、滑动窗口等保证可靠性,采用延迟应答、捎带应答提高效率;4)编程示例:展示了简单通信、全双工聊天和文件传输的实现,并分析了粘包问题及解决方法。文章详细阐述了TCP报文头结构和关键函数接口,为网络编程提供了实用参考。

Dlrb1211的博客 263

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Linux网络编程:构建TCP客户端的艺术与实践

本文介绍了如何在Linux环境下使用C语言构建TCP客户端。首先解释了TCP协议的核心特性,包括面向连接、可靠传输、流量控制和拥塞控制,并通过三次握手示意图展示了连接建立过程。然后详细讲解了构建TCP客户端的完整流程,包括创建Socket、配置服务器地址、建立连接、数据交换和优雅关闭连接等核心步骤,并提供了相关代码示例。最后通过一个智能天气查询客户端的案例,展示了如何将理论知识应用到实际开发中。文章采用技术文档与教学讲解相结合的风格,使用表格、流程图和代码片段等多种形式,帮助读者深入理解TCP客户端编程的关

软件科学-郝学胜 1251

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

connect、send、recv函数如何设置超时

在公司代码中看到如下设置socket connect函数超时的方法: 1.先调用WSAEventSelect将socket设置成非阻塞socket,示例: WSAEventSelect(hSocket, hNetEvent, FD_WRITE| FD_READ | FD_CLOSE | FD_CONNECT); 2.调用connect函数进行连接,如果返回错误,检测错误值是不是WSAEW

张小方的博客 2864

socket 超时设置

int nNetTimeout=1000;//1秒 //发送时限 setsockopt(socket,SOL_S0CKET, SO_SNDTIMEO, (char *)&nNetTimeout,sizeof(int)); //接收时限 setsockopt(socket,SOL_S0CKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int)); 这样做在Linux环境下是不会产生效果的,须如下定义:struct timeval timeout =

cfz751740465的博客 4873

linux connect 设置连接超时

原来我们实现connect()超时基本上都使用unix网络编程一书的非阻塞方式(connect_nonb),今天在网上看到一篇文章,觉得很有意思,转载如下:读Linux内核源码的时候偶然发现其connect的超时参数竟然和用SO_SNDTIMO操作的参数一致:  File: net/ipv4/af_inet.c    559       timeo = so

hemmanhui的专栏 1万+

Linux下Socket通信中非阻塞connect、select、recv 和 recvfrom、send和sendto大致讲解,附带非租塞connect代码、MSG_NOSIGNAL

linux中send函数MSG_NOSIGNAL异常消息 在服务器端用ctrl+c 来结束服务器接收进程来模拟服务器宕机的情况,结束服务 socket 进程之后,服务端自然关闭进程,可是 client 端也竟然出乎意料的关闭掉。 更改发送函数 write 为 send 并添加 MSG_NOSIGNAL 标志,重新编译,运行,中断 server,这个问题被很潇洒的解决 Linux 下当网络连接...

随意的风的专栏 7672

linux connect 设置连接超时

原来我们实现connect()超时基本上都使用unix网络编程一书的非阻塞方式(connect_nonb),今天在网上看到一篇文章,觉得很有意思,转载如下: 读Linux内核源码的时候偶然发现其connect的超时参数竟然和用SO_SNDTIMO操作的参数一致: timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_R

bj318318的博客 894
上一篇: c errorno
下一篇: 识别操作系统版本
zljjava
博客等级 码龄15年 155粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值