C++自定义connect超时时间——非阻塞套接字法

2023-11-15

一 代码

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>

#define BUFFER_SIZE 1023

int setnonblocking( int fd )     //设置套接字为非阻塞套接字
{
    int old_option = fcntl( fd, F_GETFL );
    int new_option = old_option | O_NONBLOCK;
    fcntl( fd, F_SETFL, new_option );
    return old_option;
}

int unblock_connect( const char* ip, int port, int time )
{
    int ret = 0;
    struct sockaddr_in address;
    bzero( &address, sizeof( address ) );
    address.sin_family = AF_INET;
    inet_pton( AF_INET, ip, &address.sin_addr );
    address.sin_port = htons( port );

    int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
    int fdopt = setnonblocking( sockfd );      //套接字设置为非阻塞套接字     
    ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) );
    printf("connect ret code = %d\n", ret);
    if ( ret == 0 )
    {
        printf( "connect with server immediately\n" );
        fcntl( sockfd, F_SETFL, fdopt );   //set old optional back
        return sockfd;
    }
    //unblock mode --> connect return immediately! ret = -1 & errno=EINPROGRESS
    else if ( errno != EINPROGRESS )
    {
        printf("ret = %d\n", ret);
        printf( "unblock connect failed!\n" );
        return -1;
    }
    else if (errno == EINPROGRESS)
    {
        printf( "unblock mode socket is connecting...\n" );
    }

    //use select to check write event, if the socket is writable, then
    //connect is complete successfully!
    fd_set readfds;
    fd_set writefds;
    struct timeval timeout;

    FD_ZERO( &readfds );
    FD_SET( sockfd, &writefds );

    timeout.tv_sec = time; //我们设置超时时间为1秒,原来大概需要3秒
    timeout.tv_usec = 0;

    ret = select( sockfd + 1, NULL, &writefds, NULL, &timeout );
    if ( ret <= 0 )
    {
        printf( "connection time out\n" );
        close( sockfd );
        return -1;
    }

    if ( ! FD_ISSET( sockfd, &writefds  ) )
    {
        printf( "no events on sockfd found\n" );
        close( sockfd );
        return -1;
    }

    int error = 0;
    socklen_t length = sizeof( error );
    if( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &length ) < 0 )
    {
        printf( "get socket option failed\n" );
        close( sockfd );
        return -1;
    }

    if( error != 0 )
    {
        printf( "connection failed after select with the error: %d \n", error );
        close( sockfd );
        return -1;
    }

    //connection successful!
    printf( "connection ready after select with the socket: %d \n", sockfd );
    fcntl( sockfd, F_SETFL, fdopt ); //set old optional back
    return sockfd;
}

int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
        return 1;
    }
    const char* ip = argv[1];
    int port = atoi( argv[2] );

    int sockfd = unblock_connect( ip, port, 1);  //这个值可以修改为5秒作测试
    if ( sockfd < 0 )
    {
        printf("sockfd error! return -1\n");
        return 1;
    }
    //shutdown( sockfd, SHUT_WR ); //disable read and write
    printf( "send data out\n" );
    send( sockfd, "abc", 3, 0 );
    shutdown( sockfd, SHUT_WR ); //disable read and write
    close(sockfd);
    return 0;
}

二 运行

[root@localhost test]# g++ test.cpp -o test
[root@localhost test]# ./test 192.168.0.111 11133 kkk              //该IP不存在
connect ret code = -1
unblock mode socket is connecting...
connection time out
sockfd error! return -1
[root@localhost test]# ./test 192.168.0.110 11133 kkk              //该IP是本机IP
connect ret code = -1
unblock mode socket is connecting...
connection failed after select with the error: 111
sockfd error! return -1

如果把超时时间修改为5秒

[root@localhost test]# ./test 192.168.0.112 11133 kkk
connect ret code = -1
unblock mode socket is connecting...
connection failed after select with the error: 113
sockfd error! return -1

三 说明

1 SO_ERROR参考

https://blog.csdn.net/feng973/article/details/53463750

2 常见SO_ERROR

#define ECONNREFUSED    111 /* Connection refused */
#define EHOSTDOWN   112 /* Host is down */
#define EHOSTUNREACH    113 /* No route to host */

3 代码中自定义函数setnonblocking,用于设置套接字为非阻塞套接字。然后定义一个函数unblock_connect用于连接,并且设置为1秒作为超时时间。而实际的超时返回是通过select函数来实现的。

192.168.0.111是Linux主机IP的同一网段的一个假IP,原来阻塞超时3秒作用,所以修改为1秒后,会走超时分支,说明我们自定义的超时生效了。

192.168.0.110是本机IP,它返回的错误码是111,拒绝连接。

192.168.0.111是Linux主机IP的同一网段的一个假IP,把代码的超时时间从1秒改为5秒,连接错误码是113,即没有路由到主机。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++自定义connect超时时间——非阻塞套接字法 的相关文章

  • 无法将匿名方法转换为类型“System.Windows.Threading.DispatcherPriority”,因为它不是委托类型

    谁能解释我需要做什么才能克服这个错误 无法将匿名方法转换为类型 System Windows Threading DispatcherPriority 因为它不是委托类型 private void Test object sender ba
  • 有没有办法为向量采用内存资源?

    我已经开始在我的项目中使用 pmr allocators 并且我已经看到使用它们带来了很多性能提升和优势 我使用的分配器与我在下面的简单示例中展示的非常相似 include
  • 除了第一列之外,Gridview 行可点击?

    我使用以下代码使 gridview 的整行可单击 protected void gridMSDS RowDataBound object sender GridViewRowEventArgs e if e Row RowType Data
  • System.MissingMethodException:找不到方法?

    以前工作的 ASP NET WebForms 应用程序现在抛出此错误 System MissingMethodException 找不到方法 The DoThis方法位于同一个类上 它应该可以工作 我有一个这样的通用处理程序 public
  • Ruby 解释器嵌入到 C 代码中

    我只是尝试书中的一个简单例子 我有一个 sum rb 文件 class Summer def sum max raise Invalid maximum max if max lt 0 max max max 2 end end 还有一个
  • ASP .NET MVC 5 - 客户地址一对一关系

    我在这里查看了论坛 实际上发现了一些类似的问题 但不是相同的问题 类似的解决方案没有给我正确的答案 我正在使用实体框架和代码优先方法来处理 ASP NET MVC 5 我想建立客户 gt 地址一对一关系的模型 我建模的是 客户等级 publ
  • 实体框架 5 不清除导航属性

    我在 Entity Framework 5 中遇到了这个奇怪的问题 我在其中一个实体中有一个导航属性 我想将其设置为null 但由于某种原因 该属性只有在我第二次调用该属性时才会被清除 using var db new Entities v
  • 混合 VS2012 平台工具集

    我们正在从 VS2005 切换到 VS2012 update 2 我们正在构建大量 主要是控制台 本机 C 无 MFC ATL 可执行文件 它们使用几个常见的静态链接库 这些可执行文件主要在 Win7 计算机上运行 但有些也部署在较旧的 X
  • 如何从c++调用python

    我是Python新手 我尝试像这样从 C 调用 python 脚本 在 Raspberry Pi 中 std string pythonCommand python Callee py a b int res system pythonCo
  • tcmalloc/jemalloc 和内存池之间有什么区别(以及选择的理由)?

    tcmalloc jemalloc是改进的内存分配器 还引入了内存池以更好地分配内存 那么它们之间有什么区别以及在我的应用中如何选择它们呢 这取决于您的程序的要求 如果您的程序有更多的动态内存分配 那么您 需要从可用的分配器中选择一个内存分
  • C#中如何将委托转换为对象?

    我正在使用反射类来调用其他 dll 上的一些方法 方法的参数之一是委托类型 我想通过使用反射来调用这个方法 所以我需要将函数参数作为对象数组传递 但我找不到任何关于 如何将委托转换为对象 提前致谢 委托是一个对象 只需像平常一样创建预期的委
  • 将 libpng 链接到 android 原生项目

    我在尝试在本机 Android 项目中加载 libpng 时遇到问题 编译器似乎无法识别 libpng 函数 但可以识别类型 如 png byte 它可以正常编译类型 但如果我添加函数 则会抛出错误 这是编译输出 Windows 7 cmd
  • 为什么 C# 编译的正则表达式比等效的字符串方法更快?

    每次我必须对字符串执行简单的包含或替换操作 其中我正在搜索的术语是固定值 时 我发现如果我获取示例输入并对其进行一些分析 则使用编译的正则表达式是几乎 总是比使用 String 类中的等效方法更快 我尝试过比较多种方法 hs是要搜索的 干草
  • 第一个随机数始终小于其余随机数

    我碰巧注意到 在 C 中 使用 std rand 方法调用的第一个随机数大多数时候都明显小于第二个随机数 关于 Qt 实现 第一个几乎总是小几个数量级 qsrand QTime currentTime msec qDebug lt lt q
  • STL 向量、迭代器和插入 (C++)

    我有一个将向量的迭代器传递到的方法 在这个方法中 我想向向量中添加一些元素 但我不确定当只有迭代器时这是否可行 void GUIComponentText AddAttributes vector
  • Python 中的 C 指针算术

    我正在尝试将一个简单的 C 程序转换为 Python 但由于我对 C 和 Python 都一无所知 这对我来说很困难 我被 C 指针困住了 有一个函数采用 unsigned long int 指针并将其值添加到 while 循环中的某些变量
  • Android NDK - 仅用 C/C++ 编写

    有没有一种可能的方法可以使用 C C 编写整个 NDK 应用程序 而无需像 hello jni 示例项目 HelloJni java 中那样的 Java 入门 类 以某种方式创建一个 HelloJni c 来执行相同的操作 从 Androi
  • 为什么没有参数的函数(与实际函数定义相比)可以编译?

    我刚刚看到某人的 C 代码 我很困惑为什么要编译它 有两点我不明白 The 函数原型与实际函数定义相比没有参数 中的参数函数定义没有类型 include
  • AddressAccessDeniedException :无需 netsh 即可解决它?

    我遇到了异常AddressAccessDeniedException因为我的processus没有注册URL的权限 我首先以管理员身份运行我的程序 好的 它成功了 但我现在想要分发我的应用程序 并且我希望每个用户都能够运行它 而不必成为管理
  • GetActiveObject() 与 GetObject() -- MK_E_UNAVAILABLE 错误

    All 我在将一些 VBA 代码转换为 C 时遇到一些问题 我们有一个充当本地 COM 服务器的第 3 方应用程序 在我们使用的VBA代码中获取对象 获取对现有对象的引用 e g Set appHandle GetObject ProgId

随机推荐

  • CTF签到题

    提示输入口令zhimakaimen 但是查看源代码发现输入框对长度有限制 最长只能输入10位 使用firefox插件firebug chrome控制台可直接对manlength值进行修改 改为大于11 即可输入 也可以使用burpsuite
  • Nginx常用命令以及升级(window)

    nginx Windows作为标准控制台应用程序 不是服务 运行 可以使用以下命令对其进行管理 start nginx 启动Nginx nginx s stop fast shutdown 快速停止 nginx s quit gracefu
  • 基础css-flex布局基础属性

    1 flex布局 弹性布局 伸缩布局 设置当前盒子为弹性盒子 display flex 设置主轴方向的对齐方式 justify content justify content center 设置侧轴方向的对齐方式 align items a
  • replace(),IndexOf(),substring() ,lastIndexOf() ,split() ,pollFirst() ,pollFirst()

    replace pattern replacement 使用replacement替换pattern 如果pattern是字符串只替换第一个匹配项 如果pattern是正则表达式则替换每次匹配都要调用的回调函数 实例 String a 1
  • win10 系统开启自带热点,手机无法连接(连接超时)

    win10开始自带热点 手机成功连接 颇费周折 所以在此记录一下 也给其他人一个参考 今天想在win10上安装个WIFI软件 好让手机连接 结果无意间发现win10自带了热点功能 于是赶紧打开 手机的WIFI列表也显示出来了 本以为就这样愉
  • 国际MES供应商与产品大全

    最近花了一点时间 将国际上知名的MES厂商和其产品整理了一下 如下 ABB ABB 苏黎世 瑞士 是一个240亿美元的自动化和电力技术的全球业务的供应商 它的制造软件利用其控制及自动化产品通用解决方案的一部分 其系统800xa控制体系结构
  • Android 自定义播放暂停按钮图片

    Android 自定义播放暂停按钮图片 在开发Android应用程序时 我们经常需要使用播放暂停按钮来控制媒体播放器的状态 虽然Android提供了默认的播放暂停按钮 但有时候我们希望根据设计需求自定义这些按钮的外观 在本文中 我将详细介绍
  • 嵌入式毕设分享 自动晾衣架设计与实现(源码+硬件+论文)

    文章目录 0 前言 1 主要功能 2 硬件设计 原理图 3 核心软件设计 4 实现效果 5 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学
  • 解决tmux启动「can't create socket」的问题

    Tmux是终端重度用户的好帮手 你再也不用担心以下问题 任务运行一半要下班 发现忘记使用nohup 网络不稳定 终端会掉线 有人找我开会 切换有线 无线会掉线 我入职以后 一直在开发机里面使用tmux和screen 在我发现tmux之前 最
  • Java的循环

    目录 1 while循环 2 do while循环 3 for 循环 1 while循环 while循环结构 语法结构 初始值 while 条件 循环操作代码块 迭代代码 执行规律 1 首先执行一次初始值 2 然后判断条件 如果条件为tru
  • ESP32的WIFI的STA模式&调控ESP32蓝牙和WIFI发射功率

    以下相关API接口的定义可进入l乐鑫官方查看 Wi Fi 库 ESP32 ESP IDF 编程指南 v4 4 文档 STA模式配置过程 include
  • springboot 获取当前日期_Spring Boot获取时间

    运行环境新建测试类 package com wusiyao websockets service import org springframework stereotype Service import java text SimpleDa
  • 【Linux后端服务器开发】常用开发工具

    目录 一 apt yum 二 gcc g 三 make makefile 四 vi vim 五 gdb 一 apt yum apt 和 yum 都是在Linux环境下的软件包管理器 负责软件的查找 安装 更新与卸载 apt 是Ubuntu系
  • 小程序经典案例

    1 上拉触底事件 data colorList isloding false getColors this setData isloding true 需要展示 loading 效果 wx showLoading title 数据加载中 w
  • Java学习笔记 03

    相关文章 Java学习笔记 01 概论 Java学习笔记 02 快速之旅 Java环境配置及HelloWorld程序 引言 写这篇文章 主要是为了以后能快速复习Java的基础语法 同时 帮助有C 等语言基础的同学快速入门Java 目录 一
  • SmartFusion从FPGA到ARM系列教程

    前言 本系列教程 将会以Microsemi SmartFusion一代芯片A2F200M3F为例 简单介绍片上ARM Cortex M3 硬核 MCU 基本外设的使用 及其与FPGA逻辑模块进行交互的示例 在学习片上硬核ARM Cortex
  • 网上阅卷系统php源码,又开源了,网上阅卷系统自动识别功能代码

    想让自己轻松点就要让计算机多为你做点 前几天一个朋友找到我让我做一个网上阅卷系统 就是实现这么几个功能 高速扫描仪扫描试卷后得到一张一张的图片 软件的功能就是处理图片 计算成绩 再详细点就是自动识别考生涂的学号 自动识别考生的选择题答案并记
  • css设计引言,HTML5与CSS3设计模式 引言(3)

    引言 3 2 代码清单2 浮动下沉首字示例 HTML pclass hanging indent spanclass hanging dropcap H span anging Dropcap p CSS hanging indent pa
  • 2022-渗透测试-git提权(Linux)

    目录 1 什么是提权 2 git提权命令 3 git的使用 1 什么是提权 提权就是通过各种办法和漏洞 提高自己在服务器中的权限 以便控制全局 利用漏洞的最终目的是获取被测系统的最高权限 即Windows中管理员账户的权限 或Linux中r
  • C++自定义connect超时时间——非阻塞套接字法

    一 代码 include