• libevent I/O示例


    I/O示例使用一个windows平台上服务器/客户端的例子来演示。由于为了减少代码篇幅等各种由于本人懒而产生的原因,以下代码没有做错误处理以及有些小问题,但是我想应该不影响演示,大家多包涵。

    服务器代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    #include <stdio.h>  
     
    #define WIN32_LEAN_AND_MEAN  
    #include <windows.h>  
    #include <winsock2.h>  
     
    #include "event.h"
    #include "event_struct.h"
    #include "evutil.h"
     
    #define  PORT 4000
    #define  IP_ADDRESS "172.16.80.101"
    #define  MEM_SIZE    1024
     
    struct event_base* base;
     
    struct sock_ev
    {
        struct event* read_ev;
        struct event* write_ev;
        char* buffer;
    };
     
    void release_sock_event(struct sock_ev* ev)
    {
        event_del(ev->read_ev);
        free(ev->read_ev);
        free(ev->write_ev);
        free(ev->buffer);
        free(ev);
        return;
    }
     
    void on_write(int sock, short event, void* arg)
    {
        char* buffer = (char*)arg;
        send(sock, buffer, strlen(buffer), 0);
     
        printf("on_write ");
     
        free(buffer);
        return;
    }
     
    void on_read(int sock, short event, void* arg)
    {
        struct event* write_ev;
        int size;
        struct sock_ev* ev = (struct sock_ev*)arg;
     
        printf("on_read ");
     
        ev->buffer = (char*)malloc(MEM_SIZE);
        memset(ev->buffer, 0, MEM_SIZE);
     
        size = recv(sock, ev->buffer, MEM_SIZE, 0);
        printf("receive data:%s, size:%d ", ev->buffer, size);
        if (size == 0)
        {
            release_sock_event(ev);
            close(sock);
            return;
        }
     
        event_assign(ev->write_ev, base, sock, EV_WRITE, on_write, ev->buffer);
        event_add(ev->write_ev, NULL);
        return;
    }
     
    void on_accept(int sock, short event, void* arg)
    {
        struct sockaddr_in cli_addr;
        int fd, sin_size;
     
        struct sock_ev* ev = (struct sock_ev*)malloc(sizeof(struct sock_ev));
     
        printf("on_accept ");
     
        ev->read_ev = (struct event*)malloc(sizeof(struct event));
        ev->write_ev = (struct event*)malloc(sizeof(struct event));
        sin_size = sizeof(struct sockaddr_in);
     
        fd = accept(sock, (struct sockaddr*)&cli_addr, &sin_size);
        event_assign(ev->read_ev, base, fd, EV_READ|EV_PERSIST, on_read, ev);
        event_add(ev->read_ev, NULL);
        return;
    }
     
    int main(int argc, char* argv[])
    {
        WSADATA  ws;
        SOCKET srvSock;
        struct sockaddr_in sockAddr;
        struct event ev_listen;
     
        WSAStartup(MAKEWORD(2,2), &ws);
        srvSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     
        sockAddr.sin_family      = AF_INET;
        sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
        sockAddr.sin_port        = htons(PORT);
        memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
     
        bind(srvSock, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
        listen(srvSock, 10);
     
        base = event_base_new();
        event_assign(&ev_listen, base, srvSock, EV_READ|EV_PERSIST, on_accept, NULL);
        event_add(&ev_listen, NULL);
     
        event_base_dispatch(base);
     
        closesocket(srvSock);
        WSACleanup();
     
        return 0;
    }
     
     

    客户端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #include "stdafx.h"
     
    #include <stdio.h>
    #define WIN32_LEAN_AND_MEAN  
    #include <windows.h>  
    #include <winsock2.h>  
     
    #include "event.h"
    #include "event_struct.h"
    #include "evutil.h"
     
    #define  PORT 4000
    #define  IP_ADDRESS "172.16.80.101"
     
     
    int main(int argc, char* argv[])
    {
        WSADATA  ws;
        SOCKET cltSocket;
        struct sockaddr_in sockAddr;
        int Ret = 0;
         
        WSAStartup(MAKEWORD(2,2), &ws);
        cltSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     
        sockAddr.sin_family = AF_INET;
        sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
        sockAddr.sin_port = htons(PORT);
        memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
        connect(cltSocket,(struct sockaddr*)&sockAddr, sizeof(sockAddr));
     
        //send
        char SendBuffer[MAX_PATH] = "test";
        Ret = send(cltSocket, SendBuffer, (int)strlen(SendBuffer), 0);
        printf("send size=%d. ", Ret);
     
        //recv
        char recvBuf[50] = {0};
        if( 0 > recv(cltSocket, recvBuf, 50, 0) )
        
            printf("recv fail. "); 
            return 0;     
        }  
        printf("%s ", recvBuf);
     
        while(1)
        {
            Sleep(1000);
        }
        closesocket(cltSocket);
        WSACleanup();
        return 0;
    }


    服务器的功能主要是接收客户端发来的数据,并返回给客户端。

          客户端的功能主要是连接服务器后向服务器发送数据,然后读取服务器发来的数据。

          下面分下以下代码流程:

          客户端就不分析了,都是老套路。

          服务器端:

    (1)      首先添加一个永久的读类型的事件,指定的文件描述符是我们监听的socket。当有客户端来connect,这个事件会触发,触发回调函数on_accept()

    (2)      on_accept()accept后,在新的文件描述符上添加一个永久的读事件,当文件操作符可读,调用on_read()读取。

    (3)      on_read()中为了将数据写会给客户端,添加了一个写事件,这次的写事件不是永久的,只会触发一次,因为我们只将读取到的数据回给客户端一次。当文件描述符可写,触发回调函数on_write()写入给客户端。

    (4)      On_write()写入数据。

  • 相关阅读:
    企业级Nginx负载均衡与keepalived高可用实战(一)Nginx篇
    Elasticsearch由浅入深(十一)内核原理
    Elasticsearch由浅入深(十一)索引管理
    Elasticsearch由浅入深(十)搜索引擎:相关度评分 TF&IDF算法、doc value正排索引、解密query、fetch phrase原理、Bouncing Results问题、基于scoll技术滚动搜索大量数据
    Elasticsearch由浅入深(九)搜索引擎:query DSL、filter与query、query搜索实战
    Elasticsearch由浅入深(八)搜索引擎:mapping、精确匹配与全文搜索、分词器、mapping总结
    Elasticsearch由浅入深(七)搜索引擎:_search含义、_multi-index搜索模式、分页搜索以及深分页性能问题、query string search语法以及_all metadata原理
    Elasticsearch由浅入深(六)批量操作:mget批量查询、bulk批量增删改、路由原理、增删改内部原理、document查询内部原理、bulk api的奇特json格式
    Elasticsearch由浅入深(五)_version乐观锁、external version乐观锁、partial update、groovy脚本实现partial update
    Elasticsearch由浅入深(四)ES并发冲突、悲观锁与乐观锁、_version乐观锁并发
  • 原文地址:https://www.cnblogs.com/solohac/p/4154188.html
Copyright © 2020-2023  润新知