网络编程(七)网络超时检测

news2024/10/29 13:14:10

文章目录

  • 一、概念
  • 二、实现方式
    • (一) 使用select实现超时检测
      • 1. select函数补充说明:
      • 2. 使用示例
      • 3. 输出结果
    • (二) 使用setsockopt函数
      • 1. 函数定义
      • 2. 获取发送缓冲区和接收缓冲区的大小
      • 3. 端口复用
      • 4. 设置超时时间
    • (三) alarm
      • 1. 相关概念
      • 2. sigaction

一、概念

介于阻塞和非阻塞之间,可以自己设置一个时间,在设置的时间内,如果没数据就阻塞等待,如果设置的时间到了还没数据,则立即切换为非阻塞。

二、实现方式

(一) 使用select实现超时检测

1. select函数补充说明:

#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
          fd_set *exceptfds, struct timeval *timeout);
	其中 最后一个参数 timeout 就是超时时间
    NULL 永久阻塞 直到就绪为止
    也可以使用下面的结构体指定超时时间
    struct timeval {
        long    tv_sec;         /* 秒 */
        long    tv_usec;        /* 微秒 */
    };
    如果结构体的两个成员都为 0  则表示非阻塞

返回值:
    成功 就绪的文件描述符个数
    失败 -1 重置错误码
    超时  0
  • 注:
  • select采用倒计时方式计时,如果在循环中使用,需要每次重置时间
  • 超时时,select会返回0

2. 使用示例

#include <my_head.h>

int main(int argc, char const *argv[])
{
    if(3 != argc){
        printf("Usage:%s Ipv4 port\n",argv[0]);
        exit(-1);
    }
    //创建套接字
    int sockfd=0;
    if(-1 ==(sockfd = socket(AF_INET,SOCK_STREAM,0))){
        ERR_LOG("socket error");
    }
    //填充结构体
    struct sockaddr_in serveraddr;
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
    serveraddr.sin_port=htons(atoi(argv[2]));
    socklen_t serverlen = sizeof(serveraddr);
    //绑定
    if(-1 == bind(sockfd,(struct sockaddr *)&serveraddr,serverlen)){
        ERR_LOG("bind error");
    }
    //开启监听
    if(-1 ==listen(sockfd,5)){
        ERR_LOG("listen error");
    }
    //创建集合
    fd_set readfds;
    FD_ZERO(&readfds);
    fd_set tempfds;
    FD_ZERO(&tempfds);
    int acceptfd=0;
    int max_fd=0;
    int ret=0;
    int i=0;
    int nbytes=0;
    char buff[128]={0};
    //将套接字加入集合
    FD_SET(sockfd,&readfds);
    max_fd=max_fd>sockfd?max_fd:sockfd;
    struct timeval tm;
    while(1){
        tm.tv_sec=5;
        tm.tv_usec=0;
        tempfds = readfds;
        if(-1 == (ret = select(max_fd+1,&tempfds,NULL,NULL,&tm))){
            ERR_LOG("select error");
        }else if(0 == ret){
            printf("已经五秒没有fd就绪了\n");
            continue;
        }
        printf("有fd就绪\n");
        //说明有fd就绪了,判断是不是sockfd
        for(i=3;i<max_fd+1 && 0<ret;i++){
            //先判断是不是这个fd就绪了
            if(FD_ISSET(i,&tempfds)){
                ret--;
                //判断就绪的fd是不是sockfd
                if(sockfd == i){//说明有新的客户端接入
                    if(-1 == (acceptfd = accept(i,NULL,NULL))){
                        ERR_LOG("accept error");
                    }
                    //将新的acceptfd加入集合
                    FD_SET(acceptfd,&readfds);
                    max_fd=max_fd>acceptfd?max_fd:acceptfd;
                    printf("用户[%d]连接\n",i);
                }else{//说明是已连接的客户端要通信
                    printf("接收到用户[%d]的消息\n",i);
                    if(-1 == (nbytes = recv(i,buff,sizeof(buff),0))){
                        ERR_LOG("recv error");
                    }else if(0 == nbytes){
                        printf("用户[%d]断开连接\n",i);
                        //从集合中删除
                        FD_CLR(i,&readfds);
                        close(i);
                        continue;
                    }
                    if(!strcmp(buff,"quit")){//用户退出
                        printf("用户[%d]退出\n",i);
                        //从集合中删除
                        FD_CLR(i,&readfds);
                        close(i);
                        continue;
                    }
                    //正常数据处理
                    printf("用户[%d]发送消息[%s]\n",i,buff);
                    strcat(buff,"T^T");
                    if(-1 == send(i,buff,sizeof(buff),0)){
                        ERR_LOG("send error");
                    }
                }
            }
        }
    } 
    close(sockfd);
    return 0;
}

3. 输出结果

在这里插入图片描述

(二) 使用setsockopt函数

1. 函数定义

#include <sys/types.h>
#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname,
          void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
          const void *optval, socklen_t optlen);

功能:设置或者获取套接字属性
参数:
    sockfd:要操作的套接字
    level:选项的级别
        套接字API级别  SOL_SOCKET
        TCP级别       IPPROTO_TCP
        IP级别        IPPROTO_IP
    optname:选项的名字
        套接字API级别
            SO_BROADCAST  允许发送广播
            SO_RCVBUF     接收缓冲区的大小
            SO_SNDBUF     发送缓冲区的大小
            SO_RCVTIMEO   接收超时时间
                参数是一个 struct timeval 结构体
                如果超时了 调用会返回-1 错误码 为 EAGAIN
            SO_SNDTIMEO   发送超时时间
            SO_REUSEADDR  允许端口复用
        TCP级别
            TCP_NODELAY   关闭Nagle算法
        IP级别
            IP_ADD_MEMBERSHIP  设置加入多播组
    optval:选项的值,没有特殊说明时,一般是int型指针;1打开;0关闭
    optlen:optval的长度
返回值:
    成功 0
    失败  -1 重置错误码
  • 注:如果参数没有特殊说明,一般是int型

2. 获取发送缓冲区和接收缓冲区的大小

#include <my_head.h>

int main(int argc, char const *argv[])
{
    int sockfd=0;
    if(-1 == (sockfd = socket(AF_INET,SOCK_STREAM,0))){
        ERR_LOG("socket error");
    }

    int snd_buff_size = 0;
    int snd_buff_size_len = sizeof(snd_buff_size);
    if(-1 == getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&snd_buff_size,&snd_buff_size_len)){
        ERR_LOG("getsockopt error");
    }
    printf("Sendbuff:%dKB\n",snd_buff_size/1024);
    
    int recv_buff_size = 0;
    int recv_buff_size_len = sizeof(recv_buff_size);
    if(-1 == getsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&recv_buff_size,&recv_buff_size_len)){
        ERR_LOG("getsockopt error");
    }
    printf("Recvbuff:%dKB\n",recv_buff_size/1024);
    return 0;
}

输出结果:
在这里插入图片描述

  • 注:默认 发送缓冲区16k,接收缓冲区128k。

3. 端口复用


4. 设置超时时间


(三) alarm

1. 相关概念

2. sigaction

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1844136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日复盘-202406020

今日关注&#xff1a; 20240620 六日涨幅最大: ------1--------300462--------- 华铭智能 五日涨幅最大: ------1--------300462--------- 华铭智能 四日涨幅最大: ------1--------300462--------- 华铭智能 三日涨幅最大: ------1--------300462--------- 华铭智能 二日涨幅最…

华为数通企业面试笔试实验题

1. 笔试题 1.1 实验拓扑 1.2 实验要求 公司A为小型销售公司,需要实现基本上网功能,蓝色部分为外网线,提供DHCP服务 DnsServer:114.114.114.114 帮助网管排查某一台计算机在某一台交换机的某个端口 2. 操作步骤 配置路由器相关的LAN侧接口IP地址 配置DHCP项,要求有PC1与PC2…

关于椭圆的方程(有Python画的动图)

关于椭圆的方程&#xff08;有Python画的动图&#xff09; flyfish 几何定义 椭圆是平面上所有到两个固定点&#xff08;焦点&#xff09;的距离之和为常数的点的集合。这两个固定点叫做焦点。 解析几何描述 设椭圆的两个焦点为 F 1 F_1 F1​ 和 F 2 F_2 F2​&#xff…

Redis学习|Redis主从复制、Redis哨兵模式、缓存穿透、缓存击穿、缓存雪崩概念和相应解决方法

Redis主从复制 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(master/leader)&#xff0c;后者称为从节点(slave/follower);数据的复制是单向的&#xff0c;只能由主节点到从节点。Master以写为主&#xff0c;Slave 以…

深度解读:如何运用600+标签精准构建企业画像、快速筛选高价值企业?

启信慧眼-启信宝企业版 近年来&#xff0c;信息安全越来越得到企业与公众的重视&#xff0c;数据库作为数据基础设施的关键部件&#xff0c;是保障关键信息基础设施安全的重要前提。数据库不仅为企业提供了数据存储和管理的基础设施&#xff0c;还通过数据分析、优化和扩展等功…

php反序列化的一些知识

问题 <?php $raw O:1:"A":1:{s:1:"a";s:1:"b";}; echo serialize(unserialize($raw)); //O:1:"A":1:{s:1:"a";s:1:"b";}?> php反序列化的时按理说找不到A这个类&#xff0c;但是他没有报错&#xff0c;…

conda install xformers -c xformers/label/dev 的安装问题

在StableSR项目框架中&#xff0c;需要执行 conda install xformers -c xformers/label/dev 但是报错&#xff0c;错误显示&#xff0c;版本不匹配&#xff0c;如下所示&#xff1a; 我改用pip来安装&#xff0c;好像就不报错了&#xff1a; pip install xformers

Django使用django-apscheduler实现定时任务

定时任务可以在后台定时执行指定的代码&#xff0c;避免了很多人为操作。下面是在Django项目中如何使用定时任务的具体操作流程。 我在这里使用的 django-apscheduler库来实现定时任务。 一、安装 django-apscheduler pip install django-apscheduler二、在项目的setting.py…

vivado TIMING_PATH

描述 定时路径由设计元素之间的连接来定义。在数字中 在设计中&#xff0c;时序路径是由一对受其控制的顺序元件形成的 或者通过两个不同的时钟来启动和捕获信号。 在典型的定时路径中&#xff0c;数据在一个内的两个连续单元之间传输 时钟周期。例如&#xff0c;启动边缘发生在…

‘xxxx‘ is a program, not an importable package

程序出现报错&#xff1a;‘xxxx’ is a program, not an importable package&#xff1a;“xxxx”是一个程序&#xff0c;而不是一个可导入的包 当程序出现这种报错提示的时候&#xff0c;首先第一点要做的就是需要使用到的某个方法/函数/结构体等所在的.go文件上面的packag…

音视频开发—RTMP推流详解

RTMP&#xff08;Real-Time Messaging Protocol&#xff0c;实时消息传输协议&#xff09;是一种用于音视频和数据在互联网进行实时传输的协议&#xff0c;最初由Macromedia&#xff08;现Adobe&#xff09;开发&#xff0c;用于与Adobe Flash Player进行通信。RTMP被广泛用于流…

成都晨持绪:新手开抖音网店什么品好做

在如今这个互联网高速发展的时代&#xff0c;抖音作为一款流行的短视频平台&#xff0c;已经成为许多创业者开展线上业务的首选之地。对于刚入行的新手来说&#xff0c;开设一个抖音网店既是一个机遇也是挑战&#xff0c;选择什么样的商品销售成为成功的关键因素之一。 首要的是…

数据库异常恢复2-备份文件恢复(快速恢复的手动启动方式)

(四) 备份文件备份恢复的概念 本次所说的数据恢复有异于数据的导入导出 1. 备份工具 gbase8s数据库提供了两种工具进行完成系统物理备份、逻辑日志备份和系统恢复&#xff1a;ontape和onbar ontape&#xff1a;提供了基本的系统物理备份、日志备份和恢复能力&#xff0c;其…

java实现分类下拉树,点击时对应搜索---后端逻辑

一直想做分类下拉&#xff0c;然后选择后搜索的页面&#xff0c;正好做项目有了明确的需求&#xff0c;查找后发现el-tree的构件可满足需求&#xff0c;数据要求为&#xff1a;{ id:1, label:name, childer:[……] }形式的&#xff0c;于是乎&#xff0c;开搞&#xff01; 一…

QT自定义标题栏窗口其二:实现拖动及可拉伸效果 + 顶部全屏/侧边半屏

1、效果 2、核心代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent<

管理咨询公司的五个招聘秘密

在管理咨询中&#xff0c;人是业务&#xff1b;客户支付数百万美元&#xff0c;要求管理顾问确认问题&#xff0c;并推荐解决方案。由于收入和合规性受到威胁&#xff0c;招聘错误的成本可能非常昂贵&#xff0c;一些公司更倾向于谨慎而不是效率。然而&#xff0c;在当今竞争激…

掌握大型语言模型的 7 个基本步骤

介绍 LLMs 正在改变我们今天与科技互动的方式。这些人工智能程序能够理解和模仿人类语言。它们可以应用于数据分析、客户服务、内容创作和其他领域。但对于新手来说&#xff0c;了解如何使用它们似乎很有挑战性。本文将引导读者了解掌握大型语言模型的 7 个基本步骤。 本文还…

ROM以及ROM与RAM对比

1.ROM ROM最原始的定义是“只读存储器”&#xff0c;一旦写入原始信息则不能更改。所以ROM通常用来存放固定不变的程序、常数和汉字字库&#xff0c;甚至用于操作系统的固化。它与随机存储器可共同作为主存的一部分&#xff0c;统一构成主存的地址域。 现在已经发展出了很多R…

AI 情感聊天机器人之旅 —— 相关论文调研

开放域闲聊场景 Prompted LLMs as Chatbot Modules for Long Open-domain Conversation 发布日期&#xff1a;2023-05-01 简要介绍&#xff1a;作者提出了 MPC&#xff08;模块化提示聊天机器人&#xff09;&#xff0c;这是一种无需微调即可创建高质量对话代理的新方法&…

6.20学习总结

D - 刻录光盘https://vjudge.net/problem/%E6%B4%9B%E8%B0%B7-P2835 思路&#xff1a; 利用并查集和弗洛伊德&#xff0c;对需要传递的对象都进行标记&#xff0c;经过处理后使他们的父亲发生相应的改变&#xff0c;最后对数组进行查询累加即可 代码&#xff1a; #include<…