IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 246-Linux libevent -> 正文阅读

[系统运维]246-Linux libevent

1.句柄(Handle)
在Windows下是句柄,在Linux下就是文件描述符

2.事件多路分发器(EventDemultiplexer)
通过IO函数实现的,就是IO函数

3.事件处理器和具体事件处理器
就是回调函数

4.编译的时候要加上-levent
在这里插入图片描述
5.当程序运行时,摁Ctrl+C就会触发一个信号,就会调用信号的回调函数,就会打印出^Csig=2,程序无法通过Ctrl+C退出,可以通过Ctrl+\来退出

信号和时间如果都是永久性事件EV_PERSIST,那么Ctrl+C就一直不终止程序而且每隔5秒会打印一个time out
如果信号和时间如果都不是永久性事件EV_PERSIST,那么Ctrl+C第一次会打印出^Csig=2,第二次Ctrl+C就会按照默认情况下将程序终止,时间只会打印出一个time out
在这里插入图片描述
6.当信号和时间都不是永久性事件EV_PERSIST的情况下,Ctrl+C再过5秒后打印出time out后,程序就会自动终止
在这里插入图片描述
7.IO事件多路分发器,也就是IO函数可以监测三个队列(读/写事件,计时器事件,信号时间)上哪个上面有事件就绪,它能检测的前提是三个队列上面都必须要有数据,就是有数据让我们去处理,如果三个队列都为空,程序就会自动退出,因为IO事件没有事情可以做了

哪个队列有事件产生,就会把事件放入到就绪队列中,它会帮我们调用就绪队列中的事件对应的回调函数,如果有永久事件,还会返回回去到对应的事件队列中
在这里插入图片描述
8.event_base_disopatch(base);函数返回的方式

答案:①三个事件队列都为空,读/写队列、计时器队列、信号队列
②调用退出事件循环的方法event_base_loopexit();

9.服务器端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <event.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

struct mess
{
    struct event* c_ev;
    //arg1
    //arg2
};

int socket_init();

void recv_cb(int fd,short ev,void* arg)
{
    struct mess* p = (struct mess*)arg;
    if(ev & EV_READ)
    {
        char buff[128] = {0};
        int n = recv(fd,buff,127,0);
        if(n<=0)
        {
            //从libevent中移除fd
            event_free(p->c_ev);
            free(p);
            close(fd);
            printf("close\n");
            return ;
        }
        printf("recv(%d)=%s\n",fd,buff);
        send(fd,"ok",2,0);
    }
}

void accept_cb(int fd,short ev,void* arg)
{
    struct event_base* base = (struct event_base*)arg;
    if(ev & EV_READ)//按位与,某个位为1,说明读事件
    {
        struct sockaddr_in caddr;
        int len = sizeof(caddr);
        int c = accept(fd,(struct sockaddr*)&caddr,&len);
        if(c<0)//出错了
        {
            return ;
        }

        printf("accpet c=%d\n",c);

        struct mess *p = (struct mess*)malloc(sizeof(struct mess));
        if(p == NULL)
        {
            close(c);
            return ;
        }
        p->c_ev = event_new(base,c,EV_READ|EV_PERSIST,recv_cb,p);
        if(p->c_ev == NULL)
        {
            close(c);
            return ;
        }

        event_add(p->c_ev,NULL);
    }
}

int main()
{
    int sockfd = socket_init();
    assert(sockfd != -1);

    struct event_base* base = event_init();//定义event实例
    assert(base != NULL);

    struct event * sock_ev = event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,base);//永久事件,永久监测读事件
    assert(sock_ev != NULL);
    event_add(sock_ev,NULL);//将sockfd添加到libevent
    event_base_dispatch(base);//启动事件循环,阻塞住,监测事件队列

    event_free(sock_ev);
    event_base_free(base);

    close(sockfd);

    exit(0);
}

int socket_init()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        return -1;
    }

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(res == -1)
    {
        return -1;
    }
    
    res = listen(sockfd,5);
    if(res == -1)
    {
        return -1;
    }

    return sockfd;
}

10.客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建套接字,最后一个参数一般都是0
    assert(sockfd != -1);//断言是否创建成功
    
    struct sockaddr_in saddr;//ipv4专用的地址结构
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);//这个6000指的是服务器的端口
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//如果服务器没有运行,会失败,或者断网了,也会失败
    assert(res != -1);
    //执行到这里说明connect成功了,三次握手已经完成了
    
    while(1)
    {
        char buff[128] = {0};
        printf("input\n");
        fgets(buff,128,stdin);
        
        if(strncmp(buff,"end",3) == 0)//如果输入的是end就推出循环
        {
            break;
        }

        send(sockfd,buff,strlen(buff)-1,0);//把'\n'减掉了
        memset(buff,0,128);
        recv(sockfd,buff,127,0);
        printf("buff=%s\n",buff);
    }
    close(sockfd);
}
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 18:00:11  更:2022-03-12 18:01:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 1:57:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码