#include "local.h"
#include "utils.h"
using namespace std;
// 存放客戶(hù)端socket描述符的list
list clients_list;
int main(int argc, char *argv[])
{
int listener; //監(jiān)聽(tīng)socket
struct sockaddr_in addr, their_addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = inet_addr(SERVER_HOST);
socklen_t socklen;
socklen = sizeof(struct sockaddr_in);
static struct epoll_event ev, events[EPOLL_SIZE];
ev.events = EPOLLIN | EPOLLET; //對(duì)讀感興趣,邊沿觸發(fā)
char message[BUF_SIZE];
int epfd; //epoll描述符
clock_t tStart; //計(jì)算程序運(yùn)行時(shí)間
int client, res, epoll_events_count;
CHK2(listener, socket(PF_INET, SOCK_STREAM, 0)); //初始化監(jiān)聽(tīng)socket
setnonblocking(listener); //設(shè)置監(jiān)聽(tīng)socket為不阻塞
CHK(bind(listener, (struct sockaddr *)&addr, sizeof(addr))); //綁定監(jiān)聽(tīng)socket
CHK(listen(listener, 1)); //設(shè)置監(jiān)聽(tīng)
CHK2(epfd,epoll_create(EPOLL_SIZE)); //創(chuàng)建一個(gè)epoll描述符,并將監(jiān)聽(tīng)socket加入epoll
ev.data.fd = listener;
CHK(epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev)); //把被監(jiān)聽(tīng)的fd和監(jiān)聽(tīng)的事件放入epoll的文件描述符中
//
while(1)
{
CHK2(epoll_events_count,epoll_wait(epfd, events, EPOLL_SIZE, EPOLL_RUN_TIMEOUT));
tStart = clock();
for(int i = 0; i < epoll_events_count ; i++)
{
if(events[i].data.fd == listener) //新的連接到來(lái),將連接添加到epoll中,并發(fā)送歡迎消息
{
CHK2(client,accept(listener, (struct sockaddr *) &their_addr, &socklen));
setnonblocking(client);
ev.data.fd = client;
CHK(epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev));
clients_list.push_back(client); // 添加新的客戶(hù)端到list
bzero(message, BUF_SIZE);
res = sprintf(message, STR_WELCOME, client);
CHK2(res, send(client, message, BUF_SIZE, 0));
}else
{
CHK2(res,handle_message(events[i].data.fd)); //注意:這里并沒(méi)有調(diào)用epoll_ctl重新設(shè)置socket的事件類(lèi)型,但還是可以繼續(xù)收到客戶(hù)端發(fā)送過(guò)來(lái)的信息
}
}
printf("Statistics: %d events handled at: %.2f second(s)\n", epoll_events_count, (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
close(listener);
close(epfd);
return 0;
}
int handle_message(int client)
{
char buf[BUF_SIZE], message[BUF_SIZE];
bzero(buf, BUF_SIZE);
bzero(message, BUF_SIZE);
int len;
CHK2(len,recv(client, buf, BUF_SIZE, 0)); //接受客戶(hù)端信息
if(len == 0) //客戶(hù)端關(guān)閉或出錯(cuò),關(guān)閉socket,并從list移除socket
{
CHK(close(client));
clients_list.remove(client);
}
else //向客戶(hù)端發(fā)送信息
{
if(clients_list.size() == 1)
{
CHK(send(client, STR_NOONE_CONNECTED, strlen(STR_NOONE_CONNECTED), 0));
return len;
}
sprintf(message, STR_MESSAGE, client, buf);
list::iterator it;
for(it = clients_list.begin(); it != clients_list.end(); it++)
{
if(*it != client)
{
CHK(send(*it, message, BUF_SIZE, 0));
}
}
}
return len;
}
本文名稱(chēng):epoll
URL標(biāo)題:
http://weahome.cn/article/pigico.html