4.28 poll API介绍及代码编写

news2024/9/25 7:23:39

4.28 poll API介绍及代码编写

#include <poll.h>
struct pollfd{
	int fd;//委托内核检测的文件描述符
	short events;//委托内核检测文件描述符的什么事件
	short revents;//文件描述符实际发生的事件
};
int poll(struct pollfd *fds,nfds_t nfds,int timeout);
	-参数:
		-fds:是一个struct pollfd结构体数组,这是一个需要检测的文件描述符的集合
		-nfds:这是第一个参数数组中最后一个有效元素的下标+1
		-timeout:阻塞时长
			0:不阻塞
			-1:阻塞,当检测到需要检测的文件描述符有变化,解除阻塞
			>0:阻塞的时长,单位毫秒
	-返回值:
		-1:失败
		>0:成功,返回n表示检测到集合中有n个文件描述符发生变化

在这里插入图片描述
当检测两个事件时,使用或操作:

struct pollfd myfd;
myfd.fd=5;
myfd.events=PLLIN|POLLOUT;//同时检测读事件和写事件

代码实现
client.c

#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(){
    //1.创建一个用于通信的socket
    int fd=socket(PF_INET,SOCK_STREAM,0);
    if(fd==-1){
        perror("socket");
        return -1;
    }

    //指定连接的服务器的IP和端口
    struct sockaddr_in seraddr;
    inet_pton(AF_INET,"127.0.0.1",&seraddr.sin_addr.s_addr);
    seraddr.sin_family=AF_INET;
    seraddr.sin_port=htons(9999);

    //2.连接服务器
    int ret=connect(fd,(struct sockaddr *)&seraddr,sizeof(seraddr));
    if(ret==-1){
        perror("connect");
        return -1;
    }

    //3.连接成功了,客户端可以直接和服务端通信(接收数据,发送数据)
    int num=0;
    while(1){
        char sendBuf[1024]={0};
        sprintf(sendBuf,"send data %d",num++);
        //发送数据
        write(fd,sendBuf,strlen(sendBuf)+1);

        //接收数据
        int len=read(fd,sendBuf,sizeof(sendBuf));
        if(len==-1){
            perror("read");
            return -1;
        }else if(len>0){
            printf("read buf=%s\n",sendBuf);
        }else{
            printf("服务器已经断开连接...\n");
            break;
        }
        usleep(1000);
    }
    
    //4.通信结束,断开连接
    close(fd);
    
    return 0;
}

poll.c

#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>

int main(){
    //1、创建一个用于监听的套接字
    int lfd=socket(PF_INET,SOCK_STREAM,0);
    //本地服务器的地址信息(IP和端口)
    struct sockaddr_in saddr;
    saddr.sin_port=htons(9999);
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr=INADDR_ANY;

    //2、将监听文件描述符和本地IP和端口绑定
    bind(lfd,(struct sockaddr *)&saddr,sizeof(saddr));

    //3、设置监听,监听的fd开始工作
    listen(lfd,8);

    //初始化检测的文件描述符数组
    struct pollfd fds[1024];
    for(int i=0;i<1024;++i){
        fds[i].fd=-1;
        fds[i].events=POLLIN;//检测读事件
    }
    fds[0].fd=lfd;//下标0表示监听描述符
    int nfds=0;

    while(1){
        //调用poll系统函数,让内核帮忙检测哪些文件描述符有数据
        int ret=poll(fds,nfds+1,-1);
        if(ret==-1){
            perror("poll");
            exit(-1);
        }else if(ret==0){
            continue;
        }else if(ret>0){
            //说明检测到了有文件描述符的对应缓冲区数据发生改变
            if(fds[0].revents&POLLIN){
                //表示有新客户端连接进来
                struct sockaddr_in cliaddr;
                int len=sizeof(cliaddr);
                int cfd=accept(lfd,(struct sockaddr *)&cliaddr,&len);

                //将新的文件描述符加入到集合中
                for(int i=1;i<1024;++i){
                    if(fds[i].fd==-1){
                        fds[i].fd=cfd;
                        fds[i].events=POLLIN;
                        break;
                    }
                }

                //更新最大的文件描述符索引
                nfds=nfds>cfd?nfds:cfd;
            }

            for(int i=1;i<=nfds;++i){
                if(fds[i].revents&POLLIN){
                    //说明这个文件描述符对应的客户端发来了数据
                    char buf[1024]={0};
                    //接收数据
                    int len=read(fds[i].fd,buf,sizeof(buf));
                    if(len==-1){
                        perror("read");
                        exit(-1);
                    }else if(len==0){
                        printf("client closed...\n");
                        close(fds[i].fd);//通信结束,断开连接
                        fds[i].fd=-1;
                    }else if(len>0){
                        printf("read buf=%s\n",buf);
                        //发送数据
                        write(fds[i].fd,buf,strlen(buf)+1);
                    }
                }
            }
        }
    }

    close(lfd);

    return 0;
}

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

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

相关文章

EDA云实证Vol.13:暴力堆机器之王——Calibre

Siemens的Calibre是业内权威的版图验证软件&#xff0c;被各大Foundry厂广泛认可。用户可以直接在Virtuoso界面集成Calibre接口&#xff0c;调用版图验证结果数据&#xff0c;使用起来极为方便。 今天&#xff0c;我们就来聊聊这款软件。 版图验证是芯片设计中非常重要的一环…

3.5.1MapReduce原理详解

单机程序计算流程 输入数据—>读取数据—>处理数据—>写入数据—>输出数据 Hadoop计算流程 input data&#xff1a;输入数据 InputFormat&#xff1a;对数据进行切分&#xff0c;格式化处理 map&#xff1a;将前面切分的数据做map处理(将数据进行分类&#xf…

怎么写一份好的接口文档?

目录 前言&#xff1a; 接口文档结构 参数说明 示例 错误码说明 语言基调通俗易懂 及时更新与维护 总结 前言&#xff1a; 写一份好的接口文档有助于开发者理解和使用你的API。&#xff0c; 编写一份优秀的接口文档会让软件开发中变得更加轻松&#xff0c;更有效率。…

一个大于6的偶数,能被两个质数相加得到

一个大于6的偶数,能被两个质数相加得到 1.描述 证明&#xff1a;一个大于6的偶数,能被两个质数相加得到 2.代码 先判断输入的数据是不是大于6的偶数 编写判断某个数是不是质数的方法 从中间两侧把数相加看看能不能得到对应的偶数两个奇数相加能够得到的值 public class Main…

linux入门之进程概念上(冯诺依曼系统,系统概念与定位,PCB,fork初识)

文章目录 目录 一、认识冯诺依曼系统 二、操作系统 1.概念 2.设计os的目的 3.定位 4.如何理解管理 三、系统调用和库函数 四、进程 1.基本概念 2.描述进程-PCB 3.组织进程 4.查看进程 5.通过系统调用获取进程标识符 6.通过系统调用创建进程-fork初识 6.1fork原理…

Spring(9) IOC容器中的单例Bean的线程安全问题

目录 1.知识点回顾2.线程安全3.总结 1.知识点回顾 在 Spring 中我们可以通过 Scope 注解来指定 Bean 的创建方式。 Servcie Scope("singleton") public class UserServiceImpl implements UserService {}Scope 注解的值有两种&#xff1a; singleton&#xff1a;B…

vue3使用高德地图实现点击获取经纬度

话不多说直接上干活 在此之前你需要有高德地图的 key&#xff0c;这个自己去申请即可 1&#xff0c;首先需要在终端安装 npm i amap/amap-jsapi-loader --save 2&#xff0c;准备一个容器 <template><div id"container"></div> </templat…

Redis+Lua脚本解决高并发情况下库存超卖的问题

文章目录 一、实现思路二、实现代码 一、实现思路 二、实现代码 order.lua脚本代码&#xff1a; -- 参数列表 local productIdStr ARGV[1] local productNameStr ARGV[2] local cartQuantityStr ARGV[3] local orderId ARGV[4] local userId ARGV[5] local orderDate A…

Android 控件颜色与实际不符「解决方案」

问题复现 背景色设置为 绿色&#xff0c;然而 Button 控件却显示 紫色 解决方案 这是由于 Theme 修改导致&#xff0c;只需要修改配置文件 themes.xml 中 parent 属性 即可 如果找不到该文件&#xff0c;先将工程结构展示改为 Project 即可 原配置&#xff1a; <style nam…

【网络智能化】网络杂谈(9)之如何做到网络管理智能化

涉及知识点 什么是网络管理智能化&#xff0c;基于专家系统的网络管理&#xff0c;基于智能 Agent 的网络管理&#xff0c;基于计算智能的宽带网络管理&#xff0c;深入了解网络管理智能化技术。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可去其主页…

软件业务连续性管理的意义是什么?

软件业务连续性管理是指在软件开发和运营过程中&#xff0c;确保业务能够持续进行的管理方法和实践&#xff0c;它是一种综合性的管理方法&#xff0c;旨在确保在软件系统出现故障、灾难或其他不可预测的情况时&#xff0c;能够快速、有效地恢复业务&#xff0c;以最大程度地减…

【数据分享】全国县市2000-2021年教育、卫生和社会保障数据(excel\shp格式)

《中国县域统计年鉴》是一部全面反映我国县域社会经济发展状况的资料性年鉴&#xff0c;收录了上一年度全国2000多个县域单位的基本情况、综合经济、农业、工业、教育、卫生、社会保障等方面的资料。 之前基于《中国县域统计年鉴》我们分享了2000至2021年的综合经济数据和农业…

gitee删除已上传的废弃工程

第一步:打开Git Bash或者右击电脑桌面打开也可以做到 第二步:cd到指定的工程文件夹内 dir 看一下&#xff0c;下面的项目是否正确 第三步:输入命令 git rm -r 想要删除的项目名称 第四步&#xff1a;输入命令 git commit -m 备注 第五步&#xff1a;输入命令保存 git pu…

Day.1 LeetCode刷题练习(最长公共前缀 C/C++两种解法)

题目&#xff1a; 例子&#xff1a; 分析题目&#xff1a; 主要目的&#xff1a;求出各个字符串的公共前缀 思路&#xff08;本人解法&#xff09;&#xff1a; 用所给实例来看&#xff0c;不难看出我们可以直接以竖着对应来查看是否是公共前缀 &#xff0c; 这样就有了一…

android的PopupWindow透明弹窗

1.要实现这种效果 2.可以使用这种方式 View v LayoutInflater.from(mContext).inflate(R.layout.ceshi_01, null);PopupWindow popupWindow new PopupWindow(v, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);popupWindow.showAsDropDo…

云原生(第一篇)k8s-组件说明

k8s是什么&#xff1f; go语言开发的开源的跨主机的容器编排工具&#xff1b;全称是kubernetes&#xff1b; k8s的组件&#xff1a; master&#xff1a; ①kube-apiserver 所有服务统一的访问入口&#xff0c;无论对内还是对外&#xff1b; ②kube-controller-manager 资源控…

java8新特性---lambda表达式

1、 Lambda是什么&#xff1f; Lambda 是一个匿名函数&#xff0c;我们可以把 Lambda表达式理解为是一段可以传递的代码&#xff08;将代码像数据一样进行传递&#xff09;。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格&#xff0c;使Java的语言表达能力得到了提…

linux配置git账号密码

HTTP/HTTPS Linux 在Linux环境下使用http/https协议clone/pull GitLab仓库的代码遇到这个问题。以下解决方案也适合GitHub或其他仓库如码云&#xff0c;coding。 解决方案&#xff1a; 在home目录下创建.git-credentials文件vim .git-credentials&#xff0c;输入形如https:…

重装pycharm后一直在Updating indexes

今天卸载pycharm社区版&#xff0c;安装好pycharm专业版之后&#xff0c;右下角一直显示Updating indexes 解决步骤&#xff1a; 先卸载pycharm&#xff1b;打开cmd&#xff0c;键入regedit&#xff0c;打开“注册表编辑器”&#xff1b;在“注册表编辑器”中按ctrlF&#xff…

spring是如何解析@Transactional属性的

1、查看value调用 发现并无地方调用 2、查看 transactionManager调用 发现并无地方调用 3、直接查看transaction被解析方法 SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement) 4、查看返回的解析类 Tra…