【转】C语言Socket入门非阻塞socket(connect timieout问题)

connect函数会阻塞,怎么解决? 二是但是当客户端插上网线,但是连接网络失败,也就是说能够获取到ip地址,但是和服务器是ping不通的。这种情况下connect就可能会发生阻塞,因为按照《UNIX 网络编程》中讲解,connect的在进行三次握手,如果失败情况,需要等待75s的超市时间的。第一次握手时,创建连接,connect处于阻塞状态,等待服务器accept,第二次握手成功,connect从阻塞返回,accept同样的需要收到客户端ack以后才从阻塞返回,连接建立完成。这意味着在2秒内,如果连接操作没有完成,就会超时。 阅读详情

原文:http://blog.youkuaiyun.com/hanchaoman/archive/2010/03/18/5392639.aspx

 

如果客户端想连接一个服务器端,但是不能肯定服务器端是否存在,如果存在了是否能连上,怎么判断呢? connect函数的默认行为是阻塞的,会一直等待在那里。为了判断各种情况,以及遇到错误时结束连接,我们需要使用非阻塞的socket。一个例子程序:

#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<sys/select.h>
int main(void){
 int s,r,ret,len,error;
 char buf[20];
 struct sockaddr_in sock;
 fd_set rset,wset;
 struct timeval tv;
 tv.tv_sec=10;
 s=socket(AF_INET,SOCK_STREAM,0);
 if(-1==s){ printf("socket() failed/n"); return 1; }

 if(0>fcntl(s,F_SETFL,fcntl(s,F_GETFL,0)|/*O_NDELAY*/O_NONBLOCK)){
   printf("fcntl failed/n"); return 1; }

 sock.sin_family=PF_INET;
 sock.sin_port  =htons(10080);
 sock.sin_addr.s_addr=inet_addr("197.0.0.9");/*htons(INADDR_ANY);,if a none exist ip, timeout takes effect*/

 if(-1==(ret=connect(s,(struct sockaddr*)&sock,sizeof(struct sockaddr_in)))){
  if(EINPROGRESS!=errno){/*if not fcntl->O_NDELAY, fall here*/
   printf("connect() failed:%s/n",strerror(errno)); return 1; }
 }
 if(ret==0){ printf("connection ok at once/n"); close(s); return 0; }
 FD_ZERO(&rset);
 FD_SET(s,&rset);
 wset=rset;
 if(-1==(ret=select(s+1,&rset,&wset,NULL,&tv))){
  close(s); 
  printf("select error/n"); 
 return 1; }
 if(0==ret){ close(s); printf("timeout/n"); return 1; }
 if(FD_ISSET(s,&rset)||FD_ISSET(s,&rset)){
  len=sizeof(error);
  errno=0;
  if(0>(ret=getsockopt(s,SOL_SOCKET,SO_ERROR,(void*)&error,&len))){
   printf("getsockopt error:%s/n",strerror(error));
   close(s);
   return 1;
  }
  if(error!=0){ printf("getsockopt set error:%s/n",strerror(error)); close(s); return 1; }
  printf("getsockopt success/n");
 }else{ close(s); printf("FD_ISSET error/n"); return 1; }
 if(-1==(ret=read(s,buf,sizeof(buf)))){ printf("read() failed/n"); return 1; }
 printf("ret=%d/n",ret);
 buf[ret-1]='/0';
 printf("read:%s/n",buf);
 close(s);
 return 0;
}

解释:
1. socket()得到的句柄使用fcntl函数设置了非阻塞的特性。
程序中的ip地址197.0.0.9并不存在,connect失败,select会等待(10秒),一直到timeval超时结束。

2. 如果把ip地址改为一个存在的地址,例如127.0.0,1这样,那么connect函数返回的错误值就是ECONNREFUSED。并且这种情况下select函数会立刻返回,getsockopt函数设置&error,这个可以被strerror()函数打印。----tcp协议是这么规定的。如果连接一个存在的ip,但是这个ip的机器没有监听你要连接的端口,它会返回rst报文。(当然首先是那个ip的机器支持tcp/ip协议,不过这点现在机器都支持)如果发生连接错误, 也会让socket可读和可写. 服务器没有启动, 所以肯定会发生连接错误, 这时, 连接已可读可写, select没有必要等待超时.

3. connect函数失败以后,socket句柄的状态是未定义的,应该close(s)再生成一个。
select的作用是检查描述符的状态,是否有数据过来,比如
要查读描述符,那就检查读描述符的状态,有数据来,就会返回,否则,一直等待,知道你设定的超时时间退出。
而你上面的connect的问题,不是这个。
   对于tcp/ip,每个机器只要支持tcp/ip协议,那么它一启动,就相当于有个负责tcp/ip的进程在后台运行着。再说connect,connect的过程 就是 发包收包的过程,用抓包工具可以看到。
connect的过程是:比如a去连b,以下是正常连接的情况。
a:首先发送一个数据包给b
b:收到a的包后给a回一个包。
a:收到b回的包后再给b回一个包。
这三次完成后,就是connect成功连接上,返回了。

上面的程序改为连一个存在的ip(127.0.0.1),但是对方没有在你要连得端口监听会像下面这样:
a:发一个包给b
b:发现没有监听,回rst给a
然后connect没连上结束了。

4. 其他的分析:
最初的地址如果用 INADDR_ANY,会报地址错误。
如果用合法地址,对方没有侦听,报连接被拒绝。Connection refused
如果对方在听了,但没有向你发送消息,select 认为文件描述符是不可读的。
如果三路握手完成,则 select 认为文件描述符是可写的。
写一个服务去听,客户在 select 时把 *wset 参数 设 NULL  就可以观察到 timeout。

从零到一:FAST_LIO与FAST_LIO2算法环境搭建与实战评测 本文详细介绍了FAST_LIO与FAST_LIO2算法的环境搭建与实战评测,包括算法原理、环境配置避坑指南、源码编译技巧及性能对比。FAST_LIO2凭借ikd-tree数据结构在动态环境中表现优异,处理速度提升至15ms,内存占用降低40%。文章还提供了常见问题排查和进阶优化技巧,助力开发者高效实现SLAM应用。 阅读详情

相关推荐

告别屏幕闪烁:手把手教你用示波器抓取并分析MIPI DSI信号(以RK平台为例)

本文详细介绍了如何利用示波器抓取并分析MIPI DSI信号,以解决LCD屏幕闪烁、花屏等问题。以RK平台为例,从工具准备、示波器参数配置到信号捕获与波形解读,提供了一套完整的调试方案,帮助硬件工程师快速定位和解决显示接口信号完整性问题。

weixin_33704591的博客 653

C语言Socket入门非阻塞socket(connect timieout问题)

如果客户端想连接一个服务器端,但是不能肯定服务器端是否存在,如果存在了是否能连上,怎么判断呢? connect函数的默认行为是阻塞的,会一直等待在那里。为了判断各种情况,以及遇到错误时结束连接,我们需要使用非阻塞的socket。一个例子程序:#include#include#include#include#include#include#include#includeint main(void){

hanchaoman的专栏 7916

DCM4CHEE Archive Light 应用配置-存储配置

本文介绍了在DICOM归档系统中配置和管理存储的方法,包括通过用户界面和LDAP导入两种方式。主要内容包括: 存储配置概述:用户可根据需求配置单个或多个存储设备,支持在磁盘空间不足或多任务并行时使用。存储分为Archive设备级(序列元数据存储)和Application Entity级(对象存储/元数据存储)。 用户界面操作: 设备级存储配置:通过菜单导航添加/编辑存储描述符,设置Storage ID、URI等关键参数 应用级存储引用:在设备扩展和网络AE中分别配置元数据和对象存储引用 LDAP配置方法:

洪城叮当的博客 1415

c语言 socket 非阻塞,c语言socket之非阻塞模型开发服务器与客户端。

#include int main(int argc, char* argv[]){if(argc != 3){printf("please input IP port\n");}char* ip = argv[1];unsigned int port = atoi(argv[2]);int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){pr...

weixin_34163098的博客 835

python批量生成CAD图纸

python批量生成CAD图纸

轩逸云的博客 1万+

华为CNA VRM搭建(使用vmware worfstartion搭建)

华为CNA和VRM在 vmware workstation安装使用

weixin_70595351的博客 1809

socket网络编程

socket网络编程 网络编程的步骤 常用API TCP中的accept和connect和listen的关系 UDP中的connect 广播和组播过程 服务端大量TIMEWAIT或CLOSEWAIT状态 复位报文段RST 优雅关闭和半关闭 解决TCP粘包 select可以判断网络断开吗 send和read的阻塞和非阻塞情况 网络字节序和主机序 IP地址分类及转换 select实现异步connect 为什么忽略SIGPIPE信号 如何设置非阻塞 网络编程步骤 TCP 服务端:socket -&g

清梦旅人的博客 1030

从法律文档到知识图谱

这里我们定义了两个 Pydantic 模型:Location 用于捕捉结构化的地址信息,包含可选的国家、州和地址字段;Party 用于表示合同参与方,包含必填的名称和可选的位置详情。字段描述通过告知 LLM 每个字段具体需要查找哪些信息,来辅助提取过程。"""包含结构化地址组件的位置信息。"""country: Optional[str] = Field(None, description="国家")

Anspire的博客 3030

写了一个多线程服务器(基于非阻塞socket)

大家好,我是涛哥。 最近写了一个服务端程序,能与多个客户端进行通信。那么,这个服务端是怎么实现的呢?很简单,它就是很常规的多线程服务器。 如果你还不太清楚,那我画个图,你就明白了。三个男生都追一个女生,这个女生又不好拒绝,于是与三个男生之间保持通信关系。 涛哥手绘 服务端实现 既然是多线程服务器,那么,这些线程肯定是有明确分工的。主线程来处理网络的连接,而通信线程来处理客户端与...

认知 行动 坚持 1242

YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点

本文给大家带来的改进机制是BiFPN双向特征金字塔网络,其是一种特征融合层的结构,也就是我们本文改进YOLOv11模型中的Neck部分,它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自行调节网络结构大小,同时能够达到一定的轻量化效果,为什么发BiFPN呢因为它算是YOLO系列改进中的常青树了,大家可以借鉴它的双向特征思想来创新自己的Neck结构本文的BiFPN通过yaml文件配置可以让大家自行调配其结构。

Snu77的博客 9094

socket c语言 超时时间,【转】C语言Socket入门非阻塞socket(connect timieout问题)

如果客户端想连接一个服务器端,但是不能肯定服务器端是否存在,如果存在了是否能连上,怎么判断呢? connect函数的默认行为是阻塞的,会一直等待在那里。为了判断各种情况,以及遇到错误时结束连接,我们需要使用非阻塞的socket。一个例子程序:#include#include#include#include#include#include#include#includeint main(void){...

weixin_29272301的博客 526

【头歌】链栈的基本操作及应用

另外,在算法的开始和结束时,栈都应该是空的,所以匹配到最后还要判断栈是否为空,若空,则说明匹配成功,返回1。其中表达式只包含三种括号,花括号{}、中括号[]、圆括号(),即它仅由 (、)、[、]、{、}六个字符组成。预期输出: 栈中元素依次为:12 47 5 8 6 92 45 63 75 38 4 29 弹出的栈顶元素 e=29 栈空否:0(1:空 0:否) 栈顶元素 e=4 栈的长度为11 清空栈后,栈空否:1(1:空 0:否)// 若栈不空,则用e返回S的栈顶元素,并返回OK;

qq_39977056的博客 4383

C Socket Connect 超时设置

Windows 使用 ws2_32.dll Winsock C++ connect timeout Linux 使用socket相关API C: socket connection timeout 参考文献 [1]. stackoverflow . Winsock C++ connect timeout . 2017.09 . https://stackoverflow.com/questions/46045434/winsock-c-connect-timeout [2]. stackoverf

q1009020096的博客 2573

廖雪峰Python教程[完整版]

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

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

非阻塞socket的连接 connect

连接套接字,阻塞的套接字超时时间很长无法接受,而是用非阻塞套接字时使用的方案也有多种。后者是个比较好的方法 方案1:不断重试,直到连接上或者超时: int connect_socket_timeout(int sockfd,char *dest_host, int port, int timeout) {   struct sockaddr_in address;   struct

tycoon的专栏 5183

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

设置socket connect超时时间的几种方法

BSD int connectTimeout = 30; setsockopt(sock, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT,(char *)&connectTimeout, sizeof(connectTimeout)); 1 2 Linux socket选项TCP_SYNCNT可以控制TCP连接SYN重传次数,默认为0,为0时SYN重传次数由系统参数 net.ipv4.tcp_syn_retries 控制,该系统参数默认值为6。 SYN重传次...

木牛的博客 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

非阻塞 Socoket 编程

 

rufeng18的专栏 999

c语言 socket 非阻塞,Socket Programming之select非阻塞(C语言)

server.c:#include #include #include #include #include #include #include #define BACKLOG 5 //完成三次握手但没有accept的队列的长度#define CONCURRENT_MAX 8 //应用层同时可以处理的连接#define SERVER_PORT 11332#define BUFFER_S...

weixin_34996054的博客 456

TCP Socket编程(非阻塞模式)(C++)

代码来源:《Windows网络编程》(罗莉琴,詹祖桥 主编)(如造成任何不便,请联系我删除) 服务器: [cpp] view plain copy // TcpServer.cpp : 定义控制台应用程序的入口点。   //      #include "stdafx.h"   #include    #include     

qq_39836658的博客 2305

Linux C语言 socket 多线程(循环创建多个线程,同时进行,非阻塞)

我看了一些博客,多线程网络编程用的是堵塞,也就是 pthread_join函数,可是既然是监听接口怎么能用堵塞的。 我要做的东西是:监听80端口,然后接收请求,创建一个线程完成相应任务。 我遇到的问题是:用阻塞(也就是pthread_join(thread_id))相当于单线程无法满足要求,用非阻塞(pthread_detach(thread_id))然后我的socket没反应。 问题原因...

weixin_31301271的博客 3308

socket多客户端编程实现--Select I/O 模型实现非阻塞方式

       以前在做项目的时候用到socket网络编程,当时只是简单的一对一的C/S模式,只需要简单的创建socket并绑定通信地址和端口即可完成网络通信。昨天接到中国网安的面试电话,被问到socket网络编程如何高效处理多个client的情况,当时项目并没有涉及到这方面的东西,当时的思路是为每个client开启一个线程进行处理,这种在多个线程的情况下,会消耗大量的资源。其实关于socket 网...

weixin_42715486的博客 663

网络编程--非阻塞connect

​ 看到Redis源码中主从复制的源码,对某些逻辑不是很确定。梳理了Redis非阻塞connect的大概实现之后,自己写了一个简单的版本。使用nc -l 8888当服务端,测试发现确实是可以通过监听POLLOUT事件来判断connect成功的。Linux高性能服务器编程[Ch9.5] 游双。

qq_20312079的博客 1029

非阻塞connect详解

我们先来讲connect函数(本文针对的是TCP) #include<sys/socket.h> int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen); 参数大家应该都知道,我在这里提一下,为什么第二个参数要用 struct sockaddr*? 这是因为ANSI C标准为我们定义了一...

weixin_42250655的博客 1510

Socket编程之非阻塞connect

connect()函数 头文件:     #include     #include 声明:     int connect (int sockfd,struct sockaddr * serv_addr,int addrlen); 功能:     使用套接字sockfd建立到指定网络地址serv_addr的socket连接,参数addrlen为serv_addr指向的内存空间大小,

2> /dev/null 1407

【Socket编程】非阻塞connect

阅读Skynet源码的过程中,发现一种非阻塞connect方式。以前不知道,这次好好学习一下。 文章参考自:非阻塞connect编写方法介绍(董的博客) TCP连接的建立涉及到一个三次握手的过程,鉴于RTT波动范围很大,从局域网的几个毫秒到几百个毫秒甚至广域网上的几秒。这段时间内,我们可以执行其他处理工作,以便做到并行。因此,非阻塞connect可以为我所用。 1、fcn

mick_seu的博客 1376

服务器编程心得(四)—— 如何将socket设置为非阻塞模式

只要将accept4()最后一个参数flags设置成SOCK_NONBLOCK即可。3. 除了创建socket时,将socket设置成非阻塞模式,还可以通过以下API函数来设置:参考:),linux下如果调用fcntl()设置socket为非阻塞模式,不仅要设置O_NONBLOCK模式,还需要在接收和发送数据时,需要使用MSG_DONTWAIT标志,即在recv,recvfrom和send,sendto数据时,将flag设置为MSG_DONTWAIT。

左雪菲的专栏 2807
上一篇: 【转】TCP/IP详解学习笔记(7)-广播和多播
下一篇: 【转】逆向小试 ―― QQ 自动登录器原理分析
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值