connect()函数阻塞问题
方法一:采用select
在学习嵌入式Linux网络编程中,很多同学都发现了一个问题,那就是调用connect函数时,如果服务端关闭,客户 端调用connect()函数时,发现阻塞在那里,而且利用ctrl+c信号去停止客户端程序时,需要等待一个较为长的时间才能响应了,这个时间如果大家 细心会发现,每次都是75秒的时间。那么有没有什么比较好的办法,可以以用户能接受的一个时间响应来停止掉一个正在connect连接的客户端那?比如我
们在做一个网络控制台的程序,用户需要随时可以停止掉任何一个网络服务连接,那么对于这样一个需要等待75秒时间才能反馈出服务状态的程序,用户是无法接 受的。
对于如何解决这个问题,我们可以分析下,要想完成用户在一个能接受的时间里迅速反馈出服务 端已经关闭的状态,那么我们的程序应该做到在一个规定的时间片内,可以捕获到用户发出的控制状态,然后处理用户的需求。那么要做到可以在规定的时间片内捕 获用户的控制状态,就必须禁止让我们的connect()函数阻塞75秒的情况发生,也就是说,要让connect()函数变为非阻塞状态才行。
好了,现在解决问题的关键就是如何把connect变为非阻塞状态了,我们知道,socket编程的操作对象是socket,而socket他又属于系统描述符类型,那么对于系统描述符,我们是怎么操作他变为非阻塞的那?是利用fcntl()函数或者ioctl()函数。
想到这里,好像问题应该已经解决了,但是我们调试发现,在服务端出现错误的时候,connect确实马上返回,但是,如果服务端正确那,connect还是马上返回,这样,我们无法判断connect函数是否成功了,那这个问题又该如何解决呢?
我们是否想到了一个select函数那,他具备监听文件描述符的功能,如果我们把之前的socket让select监听他是否可写,是不是问题也就解决了。
好了,那么我们总结下整个思路:
1.建立socket
2.将该socket设置为非阻塞模式
3.调用connect()
4.使用select()检查该socket描述符是否可写
5.根据select()返回的结果判断connect()结果
6.将socket设置为阻塞模式(如果你的程序不需要用阻塞模式,这步就省了,不过一般情况都是用阻塞模式,这样容易管理)
那么根据上面的6个步骤,我们写一个简单的模块程序来调试看下:
{
int
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd
< 0) exit(1);
struct
sockaddr_in serv_addr;
………//以服务器地址填充结构serv_addr
int
error=-1, len;
len
= sizeof(int);
timeval
tm;
fd_set
set;
unsigned
long ul = 1;
ioctl(sockfd,
FIONBIO, &ul); //设置为非阻塞模式
bool
ret = false;
if(
connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
{
tm.tv_set
= TIME_OUT_TIME;
tm.tv_uset
= 0;
FD_ZERO(&set);
FD_SET(sockfd,
&set);
if(
select(sockfd+1, NULL, &set, NULL, &tm) > 0)
{
getsockopt(sockfd,
SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error
== 0) ret = true;
else
ret = false;
}
else ret = false;
}
else
ret = true;
ul
= 0;
ioctl(sockfd,
FIONBIO, &ul); //设置为阻塞模式
//下面还可以进行发包收包操作
……………
}
方法二:定义信号处理函数
- sigset(SIGALRM, u_alarm_handler);
- alarm(2);
- code = connect(socket_fd, (struct
sockaddr*)&socket_st, sizeof(struct
sockaddr_in)); - alarm(0);
- sigrelse(SIGALRM);
首先定义一个中断信号处理函数u_alarm_handler,用于超时后的报警处理,然后定义一个2秒的定时器,执行connect,当系统
connect成功,则系统正常执行下去;如果connect不成功阻塞在这里,则超过定义的2秒后,系统会产生一个信号,触发执行 u_alarm_handler函数, 当执行完u_alarm_handler后,程序将继续从connect的下面一行执行下去。
其中,处理函数可以如下定义,也可以加入更多的错误处理。
- void u_alarm_handler()
- {
- }
connect()函数阻塞问题的更多相关文章
- 【网络编程】——connect函数遇见EINTR的处理
最近在公司项目中突然报错如下 “connect: Interrupted system call”, 经过查找代码发现是在创建 socket 中执行了 connect 函数失败导致.上网查阅资料发现这 ...
- 【QT】跨线程的信号槽(connect函数)
线程的信号槽机制需要开启线程的事件循环机制,即调用QThread::exec()函数开启线程的事件循环. Qt信号-槽连接函数原型如下: bool QObject::connect ( const Q ...
- UDP的connect函数
UDP的connect没有三次握手过程,内核只是检测是否存在立即可知的错误(如一个显然不可达的目的地), 记录对端的的IP地址和端口号,然后立即返回调用进程. 未连接UDP套接字(unconnecte ...
- connect函数详解
不得不说,客户端的connect函数和服务端的accept函数是一对好基友,如果客户端没有去connect, 那么服务端的accept会一直在那里傻傻地痴痴地等待,我们先来看看connect函数的原型 ...
- QT QObject::connect函数的学习
从Qobject(QObject.h)源码中可以看到QObject::connect的定义是这样的: static bool connect(const QObject *sender, cons ...
- connect函数
TCP客户用connect函数来建立与TCP服务器的连接 int connect (int sockfd, const sockaddr * servaddr, socklen_t addrlen); ...
- connect函数的用法
无论流式套接字(如TCP)还是数据报(如UDP),均可以使用connect函数.对于流式套接字,使用connect函数后,建立固定地址的连接,之后可以使用send/rev函数进行数据收发.对于数据报, ...
- 关于react-redux中的connect函数
示例代码 'use strict'; import React from 'react'; import { connect } from 'react-redux'; class demo exte ...
- Windows编程之connect函数研究
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
随机推荐
- Nginx跨域了解及模拟和解决
Nginx跨域 同源策略 何为同源: 1.协议(http/https)相同 2.域名(IP)相同 3.端口相同 详解请看我另一篇文章 https://www.cnblogs.com/you-men/p ...
- rabbitmq概念简介
AMQP协议 AMQP: Advanced Message Queue,高级队列协议. 特征: 这是一个在进程间传递异步消息的网络协议,因此数据的发送方.接收方以及容器(MQ)都可以在不同的设备上. ...
- Java多线程事务管理
今天要讨论的是"Java实现多线程单条数据事务管理",在此之前,顺便回顾一下实现多线程的几种方式 实现多线程的三种方式 一.继承Thread类 第一种方法是继承Thread类,重写 ...
- C# 8.0和.NET Core 3.0高级编程 分享笔记二:编程基础第二部分
这一篇是接上一篇笔记的第二部分. 2.5深入研究控制台应用程序 前面创建并使用了基本的控制台应用程序,下面更深入地研究它们. 控制台应用程序是基于文本的,在命令上运行的.它们通常执行需要编写脚本的简单 ...
- QT从入门到入土(一)——Qt5.14.2安装教程和VS2019环境配置
引言 24岁的某天,承载着周围人的关心,一路南下.天晴心静,听着斑马,不免对未来有些彷徨.但是呢,人生总要走陌生的路,看陌生的风景,所幸可以听着不变的歌,关心自己的人就那么多.就像是对庸常生活的一次越 ...
- F5负载均衡_monitors(健康检查)
故障现象: 后端有5台服务器,每个服务器上跑着8个应用.使用F5做应用负载调度.这40个应用里面,3-10个应用在高峰期的时候weblogic的DOS窗口显示与数据库断开连接(端口通.业务断),但是F ...
- C语言:模拟密码输入显示星号
一个安全的程序在用户输入密码时不应该显示密码本身,而应该回显星号或者点号,例如······或******,这在网页.PC软件.ATM机.POS机上经常看到.但是C语言没有提供类似的功能,控制台上只能原 ...
- [刘阳Java]_eayui-pagination分页组件_第5讲
分页组件也是很基本的应用,这里我只给出一段简单的代码 关键注意一点:分页组件可以在上面添加buttons按钮,或者自定义分页组件的外观.这些内容需要自行的查看EasyUI的API文档 <!DOC ...
- hapv-一个可以播放,下载国内主流视频的播放器
electron 开发的一个可以播放,下载国内主流视频的播放器.A player developed by electron that can play and download domestic m ...
- Scala学习——集合
Scala集合 一.数组 package top.ruandb.scala.Course04 object ArrayApp { def main(args: Array[String]): Unit ...