zoukankan      html  css  js  c++  java
  • 通信服务模型

    13.1 前言

    高性能服务器方面的讨论,主要面对TCP。

    13.2 使用多进程

    优点:好理解/简单
    缺点:每个客户端对应一个进程,资源消耗大
    适合:少量客户端
    应用:早期的apache服务器

    13.3 使用多线程

    优点:好理解/简单
    缺点:每个客户端对应一个线程,资源消耗大
    适合:少量客户端
    应用:优化过的apache服务器

    13.4 使用多路IO复用技术

    select(跨平台) epoll(linux) pselect(x) poll(unix) kqueue(freeBSD) iocp(windows平台)

    13.4.1 select

    优点:跨平台,在少量文件描述符集合中,效率高
    缺点:只能监听最多1024文件描述符

    13.4.2 epoll

    优点:支持大规模网络服务
    缺点:只支持linux

    13.5 使用多路IO服用技术和线程池

    特点:两个线程,一个线程负责epoll_wait和accept,另外一个线程负责接收和处理数据
    优点:支持大规模网络服务,并且支持高并发。

    13.6 使用多进程并发和多路IO复用技术

    特点:多个进程同时监听一个端口,如果外部有连接,多个进程通过内核实现的竞争机制,会有一个进程被唤醒。
    优点:效率非常高,nginx就是用这种方式实现的。

    13.7 使用现有通信库xs

    13.8 使用现有通信库libevent

    libevent libev ace ASIO xs

    了解:听过这个词,知道它是干嘛的。
    熟悉:把它代码下载下来,编译一下,写一个C用libevent实现hello world
    掌握:把libevent大部分的功能使用一遍
    精通:使用libevent开发一个产品
    大牛:你能找到libevent bug,甚至修改它的bug,并提交。

    • libevent代码下载

    git clone https://github.com/libevent/libevent.git

    • 编译

    sudo apt-get install automake libtool
    cd libevent
    git checkout 2.0.23-stable-rc
    ./autogen.sh
    ./configure
    make
    sudo make install

    安装位置:
    头文件:/usr/local/include
    库文件:/usr/local/lib

    openssl:加密安全
    ffmpeg:音视频处理
    iconv:文本转换

    • 编写代码

    /*==================================
    *   Copyright (C) 2016 All rights reserved.
    *   
    *   文件名称:t01_libevent_hello_world.c
    *   创 建 者:薛国良
    *   创建日期:2016年11月02日
    *   描    述:
    *
    ================================================================*/
     
    // /usr/local/include/event2/event.h
    #include <event2/event.h>
    #include <event2/listener.h>
    #include <event2/bufferevent.h>
    #include <inttypes.h>
     
     
    // socket has data in bufferevent
    void readcb(struct bufferevent *bev, void *ctx)
    {
        // read data from bufferevent...
        char buf[1024];
        // 从bufferevent中抽取数据
        int ret = bufferevent_read(bev, buf, sizeof(buf));
        if(ret < 0)
        {
            // error
            printf("error");
        }
     
        printf("%s ", buf);
    }
     
    void eventcb(struct bufferevent *bev, short what, void *ctx)
    {
        if((what & BEV_EVENT_EOF)  > 0)
        {
            printf("delete event ");
            bufferevent_free(bev);
        }
    }
     
    // listener: 监听器
    // newfd:accept返回的socket
    // addr:是对端的网络地址
    // socklen:对段的网络地址结构体的长度
    // ptr:额外参数
    void listen_cb(struct evconnlistener *listener, evutil_socket_t newfd, struct sockaddr *addr, int socklen, void *ptr)
    {
        struct event_base* evbase = evconnlistener_get_base(listener);
     
        /* add newfd to evbase */
        struct bufferevent* bev = bufferevent_socket_new(evbase, newfd, BEV_OPT_CLOSE_ON_FREE);
     
        /* setup read and event callback function */
        bufferevent_setcb(bev, readcb, NULL, eventcb, NULL);
     
        bufferevent_enable(bev, EV_READ|EV_WRITE);
    }
     
    int main()
    {
        // 类似创建一个epoll或者select对象,默认下linux下应该epoll
        // event_base是一个事件的集合
        struct event_base* evbase = event_base_new();
        // 在libevent中,事件指一件即将要发生事情,evbase就是用来监控这些事件的
        // 发生(激活)的条件的
     
        struct sockaddr_in addr;
        addr.sin_port = htons(9988);
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
     
        // 创建一个监听器事件,该监听器事件是初始化状态
        struct evconnlistener* listener =
                evconnlistener_new_bind(evbase,
                                        listen_cb,
                                        NULL,
                                        LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
                                        250,
                                        (struct sockaddr*)&addr,
                                        sizeof(addr));
     
        // 进入未决状态
        evconnlistener_enable(listener);
     
        // evbase监听它的所有未决状态的事件,进入死循环
        event_base_dispatch(evbase);
     
     
        // 释放event_base
        event_base_free(evbase);
     
        return 0;
    }
    • 编译
      g++ t01_libevent_hello_world.c -levent_core

    注意链接相应的库

    • 运行

    export LD_LIBRARY_PATH=/usr/local/lib
    ./a.out
  • 相关阅读:
    2020面试有感(1)
    多线程与异步
    GP-荧光免疫分析仪SDK 协议
    FastReport模板设计和调用
    EF的多线程与分库架构设计实现(2)
    HTML页面转化为带有水印的PDF文件
    利用 html2canvas+jsPDF 把 HTML元素 转化为PDF文件,以及遇到的坑
    前端json数据格式化显示
    单元测试——引入Vuex
    单元测试——引入vue-router和APP.vue文件
  • 原文地址:https://www.cnblogs.com/w-x-me/p/6414543.html
Copyright © 2011-2022 走看看