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,并提交。
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;
}
注意链接相应的库
export LD_LIBRARY_PATH=/usr/local/lib
./a.out