tcp服务器示例:使用epoll监听并发连接

 程序功能:监听tcp客户端连接,并用epoll监听这些客户端发送的数据,相当于一个日志接收器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <errno.h>
#include <vector>
#include <pthread.h>

#define MAX_EVENT   20
#define BUFF_SIZE   100*1024

//epoll句柄
int epfd = 0;

void add_epoll_socket(int fd, EPOLL_EVENTS et);
void delete_epoll_socket(int fd, EPOLL_EVENTS et);

int main(int argc, char *argv[])
{
    if(argc!=2)
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    //建立服务端socket,监听端口:argv[1]
    int serv_sock=socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1)
    {
        printf("socket() failed, errno=%d\n", errno);
        exit(1);
    }

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_addr.sin_port=htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1)
    {
        printf("bind() failed, errno=%d\n", errno);
        exit(1);
    }

    if(listen(serv_sock, 5)==-1)
    {
        printf("listen() failed, errno=%d\n", errno);
        exit(1);
    }

    //创建epoll句柄
    epfd = epoll_create(MAX_EVENT);
    if (epfd < 0)
    {
        printf("epoll_create() failed, errno=%d, epfd=%d\n", errno, epfd);
        exit(1);
    }

    add_epoll_socket(serv_sock, EPOLLIN);

    int i, ret, len, fd;
    struct epoll_event events[MAX_EVENT];
    char buff[BUFF_SIZE] = {0};
    char log[BUFF_SIZE] = {0};
    char *begin, *end;

    while (1)
    {
        //监听socket事件
        ret = epoll_wait(epfd, events, MAX_EVENT, 200);
        for (i = 0; i < ret; i++)
        {
            fd = events[i].data.fd;
            if (fd == serv_sock)
            {
                struct sockaddr_in client_addr;
                socklen_t addr_size = sizeof(sockaddr_in);  
                int client_sock = accept(fd, (struct sockaddr*)&client_addr, &addr_size);
                if(client_sock == -1)
                {
                    printf("accept() failed, errno=%d\n", errno);
                    continue;
                }

                char *addr = inet_ntoa(client_addr.sin_addr);
                printf("client_sock=%d, addr=%s\n", client_sock, addr);

                //不监听回送连接
                if (strcmp(addr, "127.0.0.1") != 0)
                {
                    add_epoll_socket(client_sock, EPOLLIN);
                }
            }
            else
            {
                //从缓冲区读数据,实际上需要注意tcp有粘包问题                
                len = recv(fd, buff+strlen(buff), BUFF_SIZE-strlen(buff), 0);
                //recv返回0说明socket关闭
                if (len == 0)
                {
                    delete_epoll_socket(fd, EPOLLIN);
                    close(fd);
                    continue;
                }

                printf("buff='%s'\n", buff);
                memset(buff, 0, BUFF_SIZE);
            }
        } //for
    } //while (1)

    close(epfd);
    close(serv_sock);
    return 0;
}

void add_epoll_socket(int fd, EPOLL_EVENTS evt)
{
    struct epoll_event et;
    et.data.fd = fd;
    et.events = evt;
    epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &et);
}

void delete_epoll_socket(int fd, EPOLL_EVENTS evt)
{
    struct epoll_event et;
    et.data.fd = fd;
    et.events = evt;    //fd可读事件
    epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &et);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值