《socket编程由笑嘻嘻到绝望》(epoll简单高并发服务器模型)

在网络编程中相对使用select poll 机制 ,epoll具有着很大的优势,具体优势很多文章都有讲,在这里就不再赘述了。

在下面的例子中服务直接使用命令make就可以编译,运行命令demo:

./epoll_server  127.0.0.1 6666

测试的客户端运行命令demo:

gcc -o client client.c

./client 127.0.0.1 6666
首先写Makefile
Tar = epoll_server
CC = gcc
CFLAGS = -Wall -O -g
SOURCES = $(wildcard *.c *.cpp)
OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))

$(Tar):$(OBJS)
    $(CC) $(CFLAGS) -o  $@ $< 
$(OBJS):$(SOURCES)
    $(CC) $(CFLAGS) -c $< -o $@                     
clean:
    rm -rf *.o  $(Tar)
简单的服务器模型搭建,作用主要练习epoll的使用
#include <stdio.h>       
#include <sys/types.h>          
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>  
#include <strings.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>



#define MAXFD 10
#define BUFSIZE 512

int main(int argc,char*argv[])
{
    int socketfd = 0;
    int socket_flag = 0;
    int connfd = 0;
    int epfd = 0;
    int waitFd = 0;
    int i = 0;
    int n = 0;
    char recvBuf[BUFSIZE] = {};
    char sendBuf[BUFSIZE] = "I am Baiyu";
    struct sockaddr_in server_sock_addr;
    struct sockaddr_in client_sock_addr; 
    struct epoll_event ev;
    struct epoll_event events[20];
    if(argc != 3)
    {
        printf("Usage:%s error\nPlease input ./aout ip port\n",argv[0]);
        return -1;
    }
    socketfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == socketfd){
        printf("socketfd error!\n");
        return -1;
    }

    epfd=epoll_create(256);
    ev.data.fd = socketfd;
    ev.events=EPOLLIN|EPOLLET;
    epoll_ctl(epfd,EPOLL_CTL_ADD,socketfd,&ev);

    server_sock_addr.sin_family = AF_INET;
    server_sock_addr.sin_port = htons(atoi(argv[2]));  
    server_sock_addr.sin_addr.s_addr = inet_addr(argv[1]); 

    bzero(&(server_sock_addr.sin_zero), 8);
    if(-1 == bind(socketfd,(struct sockaddr*)&server_sock_addr,sizeof(struct sockaddr))){
        printf("bind error!\n");
        return -1;
    }

    if(-1 == listen(socketfd, MAXFD) ){
        printf("listen error!");
        return -1;
    }

    for(;;){
        waitFd = epoll_wait(epfd,events,256,100);
        for(i=0;i<=waitFd;i++){
            //新的连接
            if(events[i].data.fd == socketfd){
                socklen_t length = sizeof(struct sockaddr_in);
                connfd = accept(socketfd,(struct sockaddr *)&client_sock_addr, &length);
                if(connfd<0){
                    perror("connfd<0");
                    exit(1);
                }
                char *str = inet_ntoa(client_sock_addr.sin_addr);
                printf("New IP:%s\n",str);
                ev.data.fd=connfd;
                ev.events=EPOLLIN|EPOLLET;
                //注册
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
            }
            //读操作
            else if(events[i].events == EPOLLIN){
                 if ( (socket_flag = events[i].data.fd) < 0){
                         continue;
                     } 
                if ( (n = read(socket_flag, recvBuf, BUFSIZE)) < 0) {
                        close(socket_flag);
                        events[i].data.fd = -1;
                    } 
                else if (n == 0) {
                    close(socket_flag);
                    events[i].data.fd = -1;
                }
                printf("read:%s\n",recvBuf); 
                ev.data.fd=socket_flag;
                ev.events=EPOLLOUT|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,socket_flag,&ev);
            }
            //写操作
            else if(events[i].events == EPOLLOUT){
                socket_flag = events[i].data.fd;
                write(socket_flag, sendBuf, BUFSIZE);
                ev.data.fd=socket_flag;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,socket_flag,&ev);
            }

        }

    }




    return 0;
}
测试客户端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>  
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PORT 6666  //>1024   <65535
#define MAXDATASIZE 1024

int main(int argc, char *argv[])
{

    int sockfd = 0;
    int numsize = 0;
    char buf[MAXDATASIZE];
    struct hostent *input_ip;
    struct sockaddr_in client_addr;
    if (argc != 3)
    {
        printf("usage: client error\n");    
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket error\n");
        exit(1);
    }
    if ((input_ip=gethostbyname(argv[1])) == NULL)
    {
        printf("gethostbyname error\n");
        exit(1);
    }
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(atoi(argv[2]));
    client_addr.sin_addr = *((struct in_addr *)input_ip->h_addr);
    bzero(&(client_addr.sin_zero), 8);
    if(connect(sockfd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1)
    {
        printf("connect error\n");
        exit(1);
    }
    write(sockfd, "12345678\r\n", 20) ;

    if((numsize=read(sockfd, buf, sizeof buf - 1)) == -1)
    {
        printf("recv error\n");
        exit(1);
    }
    printf("%s\n",buf);
    fflush(stdout);
    close(sockfd);
    return 0;
}

主要用于学习epoll的使用,看了一些优秀的博客,在后面的完善过程中,依然要看很多资料

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_小白鱼儿_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值