13.1 前言
高性能服務器方面的討論,主要面對TCP。linux
13.2 使用多進程
優勢:好理解/簡單
缺點:每一個客戶端對應一個進程,資源消耗大
適合:少許客戶端
應用:早期的apache服務器nginx
13.3 使用多線程
優勢:好理解/簡單
缺點:每一個客戶端對應一個線程,資源消耗大
適合:少許客戶端
應用:優化過的apache服務器git
13.4 使用多路IO複用技術
select(跨平臺) epoll(linux) pselect(x) poll(unix) kqueue(freeBSD) iocp(windows平臺)github
13.4.1 select
優勢:跨平臺,在少許文件描述符集合中,效率高
缺點:只能監聽最多1024文件描述符apache
13.4.2 epoll
優勢:支持大規模網絡服務
缺點:只支持linuxwindows
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\n", buf);
}
void eventcb(struct bufferevent *bev, short what, void *ctx)
{
if((what & BEV_EVENT_EOF) > 0)
{
printf("delete event\n");
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