溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

epoll

發(fā)布時間:2020-07-27 03:05:39 來源:網絡 閱讀:330 作者:dy_water 欄目:編程語言
#include "local.h"
#include "utils.h"

using namespace std;

// 存放客戶端socket描述符的list
list<int> clients_list;

int main(int argc, char *argv[])
{
    int listener;   //監(jiān)聽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;     //對讀感興趣,邊沿觸發(fā)

    char message[BUF_SIZE];

    int epfd;  //epoll描述符
    clock_t tStart;  //計算程序運行時間

    int client, res, epoll_events_count;

    CHK2(listener, socket(PF_INET, SOCK_STREAM, 0));             //初始化監(jiān)聽socket
    setnonblocking(listener);                                    //設置監(jiān)聽socket為不阻塞
    CHK(bind(listener, (struct sockaddr *)&addr, sizeof(addr))); //綁定監(jiān)聽socket
    CHK(listen(listener, 1));                                    //設置監(jiān)聽

    CHK2(epfd,epoll_create(EPOLL_SIZE));                         //創(chuàng)建一個epoll描述符,并將監(jiān)聽socket加入epoll
    ev.data.fd = listener;
    CHK(epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev));          //把被監(jiān)聽的fd和監(jiān)聽的事件放入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)                    //新的連接到來,將連接添加到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);                  // 添加新的客戶端到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)); //注意:這里并沒有調用epoll_ctl重新設置socket的事件類型,但還是可以繼續(xù)收到客戶端發(fā)送過來的信息
            }
        }
        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));  //接受客戶端信息

    if(len == 0)   //客戶端關閉或出錯,關閉socket,并從list移除socket
    {
        CHK(close(client));
        clients_list.remove(client);
    }
    else          //向客戶端發(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<int>::iterator it;
        for(it = clients_list.begin(); it != clients_list.end(); it++)
        {
           if(*it != client)
           { 
                CHK(send(*it, message, BUF_SIZE, 0));
           }
        }
    }

    return len;
}


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI