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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值