1、前言

最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口。当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口。我们知道端口属于网络的传输层,因此需要用ip和端口来探测,这个时候就可以用connect来探测一下,针对TCP协议,connect函数要进行TCP三次握手,如果connect成功,则说明服务器开放了某个端口,如果connect失败,则说明服务器没有开放某个端口。而connect失败是通过超时来控制的,在规定的时间内,connect会发起多次连接,一直执行到超时,才返回错误。默认情况下,connect是阻塞的,而且默认的超时时间为75s,正常情况下,检测网络的连通性都是毫秒级,如果要判断10万台服务器的,用阻塞的默认的connect去做,效率非常低下。因此采用非阻塞的connect,而且需要自定义超时间(我自定义超时时间为5s)。

2、非阻塞connect

对于阻塞式套接字,调用connect函数将激发TCP的三次握手过程,而且仅在连接建立成功或者出错时才返回;对于非阻塞式套接字,如果调用connect函数会之间返回-1(表示出错),且错误为EINPROGRESS,表示连接建立,建立启动但是尚未完成;如果返回0,则表示连接已经建立,这通常是在服务器和客户在同一台主机上时发生。

select是一种IO多路复用机制,它允许进程指示内核等待多个事件的任何一个发生,并且在有一个或者多个事件发生或者经历一段指定的时间后才唤醒它。connect本身并不具有设置超时功能,如果想对套接字的IO操作设置超时,可使用select函数。

对于select和非阻塞connect,注意两点:[1] 当连接成功建立时,描述符变成可写; [2] 当连接建立遇到错误时,描述符变为即可读,也可写,遇到这种情况,可调用getsockopt函数。

3、实现步骤

(1) 创建socket,并利用fcntl将其设置为非阻塞

(2) 调用connect函数,如果返回0,则连接建立;如果返回-1,检查errno ,如果值为 EINPROGRESS,则连接正在建立。

(3) 为了控制连接建立时间,将该socket描述符加入到select的可读可写集合中,采用select函数设定超时。

(4) 如果规定时间内成功建立,则描述符变为可写;否则,采用getsockopt函数捕获错误信息

(5) 恢复套接字的文件状态并返回。

测试代码如下所示:

#include

#include

#include

#include

#include /* See NOTES */

#include

#include

#include

#include

int main(int argc, char **argv)

{

if (argc < 3) {

printf("please input ip and port, for example ./main 120.12.34.56 80.\n");

return -1;

}

char *ipaddr = argv[1];

unsigned int port = atoi(argv[2]);

int fd = 0;

struct sockaddr_in addr;

fd_set fdr, fdw;

struct timeval timeout;

int err = 0;

int errlen = sizeof(err);

fd = socket(AF_INET,SOCK_STREAM,0);

if (fd < 0) {

fprintf(stderr, "create socket failed,error:%s.\n", strerror(errno));

return -1;

}

bzero(&addr, sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(port);

inet_pton(AF_INET, ipaddr, &addr.sin_addr);

/*设置套接字为非阻塞*/

int flags = fcntl(fd, F_GETFL, 0);

if (flags < 0) {

fprintf(stderr, "Get flags error:%s\n", strerror(errno));

close(fd);

return -1;

}

flags |= O_NONBLOCK;

if (fcntl(fd, F_SETFL, flags) < 0) {

fprintf(stderr, "Set flags error:%s\n", strerror(errno));

close(fd);

return -1;

}

/*阻塞情况下linux系统默认超时时间为75s*/

int rc = connect(fd, (struct sockaddr*)&addr, sizeof(addr));

if (rc != 0) {

if (errno == EINPROGRESS) {

printf("Doing connection.\n");

/*正在处理连接*/

FD_ZERO(&fdr);

FD_ZERO(&fdw);

FD_SET(fd, &fdr);

FD_SET(fd, &fdw);

timeout.tv_sec = 10;

timeout.tv_usec = 0;

rc = select(fd + 1, &fdr, &fdw, NULL, &timeout);

printf("rc is: %d\n", rc);

/*select调用失败*/

if (rc < 0) {

fprintf(stderr, "connect error:%s\n", strerror(errno));

close(fd);

return -1;

}

/*连接超时*/

if (rc == 0) {

fprintf(stderr, "Connect timeout.\n");

close(fd);

return -1;

}

/*[1] 当连接成功建立时,描述符变成可写,rc=1*/

if (rc == 1 && FD_ISSET(fd, &fdw)) {

printf("Connect success\n");

close(fd);

return 0;

}

/*[2] 当连接建立遇到错误时,描述符变为即可读,也可写,rc=2 遇到这种情况,可调用getsockopt函数*/

if (rc == 2) {

if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {

fprintf(stderr, "getsockopt(SO_ERROR): %s", strerror(errno));

close(fd);

return -1;

}

if (err) {

errno = err;

fprintf(stderr, "connect error:%s\n", strerror(errno));

close(fd);

return -1;

}

}

}

fprintf(stderr, "connect failed, error:%s.\n", strerror(errno));

return -1;

}

return 0;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

linux下载文件一直超时,Linux下connect超时处理(总结)相关推荐

  1. EOS中JAVA从Linux下载文件,教程 - 在Linux上安装EOS

    你想学习如何在Linux上安装EOS? 在本教程中,我们将向您展示如何在运行Ubuntu Linux的计算机上安装EOS. EOS相关教程: 在此页面上,我们提供了与EOS.IO相关的教程列表的快速访 ...

  2. linux中的文件夹压缩文件,linux将文件拷贝到目录下Linux下文件的压缩与打包详解...

    在Linux中,有很多的压缩命令.利用这些压缩命令,可以方便的从网络上下载大型的文件.同时,我们知道,Linux文件的扩展名是没有特殊意义的,不过,因为Linux下存在着许多压缩命令,所以为了方便记忆 ...

  3. Linux下载文件命令wget的一些用法

    1.介绍 wget 是一个从网络上自动下载文件的自由工具,支持通过 HTTP.HTTPS.FTP 三个最常见的 TCP/IP协议下载,并可以使用 HTTP 代理. "wget" 这 ...

  4. linux下载文件夹到本地命令行,linux下载文件到本地命令,linux下载文件到本地命令 下载工具...

    linux下载文件到本地命令,linux下载文件到本地命令 下载工具 来源:互联网/编辑:佚名/时间:2020-09-08 在手机上看 扫一扫进入手机端 linux用户命令在哪个文件夹下 用 whic ...

  5. windows命令行下访问linux,Windows支持直接访问Linux子系统文件:你的下一台Linux何必是Linux...

    原标题:Windows支持直接访问Linux子系统文件:你的下一台Linux何必是Linux 晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 微软,致力于做最好的Linux发行版. 今天, ...

  6. linux中文件链接,关于Linux中文件,链接的一些思考

    在Unix系统中,操作系统为磁盘上的文本与图像,鼠标键盘操作,网络交互等IO操作设计了一组通用API. 使他们被处理的时候可统一用字节流的方式.所以说,除了进程之外,其他的一切均可看做文件. Linu ...

  7. linux命令删除的文件怎么找回来,linux误删文件怎么恢复 linux误删命令行文件怎么恢复...

    linux误删文件怎么恢复 linux误删命令行文件怎么恢复 linux系统是不同于windows系统和mac系统的,它独特的系统操作深受广大网友喜爱.有的朋友在使用linux系统的时候,不小心把一些 ...

  8. linux connect 超时时间,Linux下connect超时处理【总结】

    1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的应用层, ...

  9. 从FTP服务器下载文件部署更新linux服务器上的服务

    作为软件测试人员,经常要发布开发的集成包.本来嘛,更新个服务,没什么大不了.但是集成包打出来,要更新的服务有9个(分别部署在三台服务器上),并且以后还会增加.如果手动更新,每次更新时间都得20分钟以上 ...

最新文章

  1. Leetcode题目:Balanced Binary Tree
  2. 【Guava】使用Guava的RateLimiter做限流
  3. 实验一个最小的PYTHON服务器编程
  4. 实际部署遇到的一些问题
  5. DeepMatching文献总结:图像拼接、图像匹配、图像检索
  6. spring整合junit问题分析
  7. map容器中删除一个元素(value)
  8. Linq 实现sql中的not in和in条件查询
  9. python安装requests库超时_【Python 库】requests 详解超时和重试
  10. 颠覆未来世界的十大科技
  11. Pinyin4j 的使用 Pinyin4jUtils工具类
  12. inventor弧度怎么标注_家里房间太大,WiFi信号覆盖不了怎么办?网件新作:分身术...
  13. 经典的面试题如果不通过其他任何变量实现两个数值类型的变量互相更换值。...
  14. java web实训项目_通知 | Java、web大前端将在南京开课啦!
  15. 搭建springmvc项目遇到的问题
  16. SpringBoot海景房出租管理系统+代码讲解
  17. (商品评价页)商品星级评分html+css+js
  18. 使用Excel对国外B2B电商平台进行描述性数据分析
  19. mysql 8安装方法_Mysql8.0.17安装教程【推荐】
  20. mysql 简述pk uk fk 的区别和对数据库性能的影响_数据库pk fk ak

热门文章

  1. python云盘服务_Python无所不能?五分钟教会你用python打造个人云盘!
  2. java 反射field_Java基础--反射之Field
  3. 博图wincc连接数据块_西门子博途WINCC 可通过创建画面模板提高编程效率
  4. Hadoop开发 Hadoop视频教程 段海涛老师Hadoop完全攻克Hadoop视频教程 Hadoop开发
  5. Javascript之 对象和原型
  6. Sublime Text 2 代码片断
  7. [转]JS获取当前对象大小以及屏幕分辨率等
  8. 码农干货系列【17】--Wind.js与Promise.js
  9. HTML 5.2 新特性介绍
  10. Database 2 Day DBA guide_Chapter3