epoll实现echo server和client

来源:互联网 发布:淘宝千人千面是什么 编辑:程序博客网 时间:2024/05/21 22:28

作为后端研发人员,竟然没搞清楚C/S模式,惭愧。。不爽。。

部分代码参考 http://blog.csdn.net/shanshanpt/article/details/7383400 感谢~~

  • server.cpp
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <errno.h>#include <sys/socket.h>         // for socket#include <netinet/in.h>         // for sockaddr_in#include <sys/epoll.h>          // for epoll#include <fcntl.h>              // for nonblocking#include <sys/resource.h>       // for 最大连接数需要setrlimit#define MAXEPOLL 10000         // 对服务器来说,这个值可以很大#define MAXLINE  1024#define PORT     6000#define MAXBACK  1000int setnonblocking(int fd) {    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFD,0) | O_NONBLOCK) == -1) {        printf("set blocking error: %d\n", errno);        return -1;    }    return 0;}int main() {    int listen_fd;    int conn_fd;    int epoll_fd;    int nread;    int cur_fds;     // 当前已经存在的fd数量    int wait_fds;    // epoll_wait的返回值    int i;    struct sockaddr_in servaddr;    struct sockaddr_in cliaddr;    struct epoll_event ev;    struct epoll_event evs[MAXEPOLL];    struct rlimit rlt; // 设置连接数所需    char buf[MAXLINE];    socklen_t len = sizeof(struct sockaddr_in);    // 1.设置每个进程允许打开的最大文件数    rlt.rlim_max = rlt.rlim_cur = MAXEPOLL;    if(setrlimit(RLIMIT_NOFILE, &rlt) == -1) {        printf("setrlimit error : %d\n", errno);        exit(EXIT_FAILURE);    }    // 2. 设置server地址    bzero(&servaddr, sizeof(servaddr));    // sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET,代表TCP/IP协议族    servaddr.sin_family = AF_INET;    // INADDR_ANY就是指定地址为0.0.0.0的地址,也就是表示本机的所有IP    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    // 必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字    servaddr.sin_port = htons(PORT);    // 3. 建立套接字    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        printf("socket error : %d ...\n", errno);        exit(EXIT_FAILURE);    }    // 4. 设置非阻塞模式    if (setnonblocking(listen_fd) == -1) {        printf("set non blocking error : %d ...\n", errno);        exit(EXIT_FAILURE);    }    // 5. 绑定    if (bind(listen_fd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) == -1) {        printf("bind error : %d ...\n", errno);        exit(EXIT_FAILURE);    }    // 6. 监听    if (listen(listen_fd, MAXBACK) == -1) {        printf("listen error : %d ...\n", errno);        exit(EXIT_FAILURE);    }    // 7. 创建epoll    epoll_fd = epoll_create(MAXEPOLL);     ev.events = EPOLLIN | EPOLLET;       // accept read    ev.data.fd = listen_fd;              // add listen_fd    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0) {        printf("epoll_ctl error : %d\n", errno);        exit(EXIT_FAILURE);    }    cur_fds = 1;    while (true) {        if ((wait_fds = epoll_wait(epoll_fd, evs, cur_fds, -1)) == -1) {             printf("epoll_wait error : %d\n", errno);            exit(EXIT_FAILURE);        }        for (i = 0; i < wait_fds; ++i) {            if (evs[i].data.fd == listen_fd && cur_fds < MAXEPOLL) {                if ((conn_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &len)) == -1) {                    printf("accept error : %d\n", errno);                    exit(EXIT_FAILURE);                }                printf("server get from client port : %d\n", cliaddr.sin_port);                ev.events = EPOLLIN | EPOLLET;                ev.data.fd = conn_fd;                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {                    printf("epoll error : %d\n", errno);                    exit(EXIT_FAILURE);                }                ++cur_fds;                continue;            }            // 处理数据            nread = read(evs[i].data.fd, buf, sizeof(buf));            if (nread < 0) {                close(evs[i].data.fd);                epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evs[i].data.fd, &ev);                --cur_fds;                continue;            }            buf[nread] = 'a';            buf[nread + 1] = '\0';            // 回写            write(evs[i].data.fd, buf, nread);        }    }    close(listen_fd);    return 0;}
  • client.cpp
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <sys/select.h>#include <sys/epoll.h>          // for epoll#include <fcntl.h>#define MAXEPOLL 10000#define MAXLINE 1024#define SERV_PORT 6000int setnonblocking(int fd) {    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFD,0) | O_NONBLOCK) == -1) {        printf("set blocking error: %d\n", errno);        return -1;    }    return 0;}void send_and_recv_epoll(int conn_fd) {    int epoll_fd;    int cur_fds;    int wait_fds;    struct epoll_event ev;    struct epoll_event evs[MAXEPOLL];    char send[MAXLINE];    char recv[MAXLINE];    int lens;    int n;    int i = 0;    FILE* fp = stdin;    epoll_fd = epoll_create(MAXEPOLL);    ev.events = EPOLLIN | EPOLLOUT | EPOLLET;    ev.data.fd = conn_fd;    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {        printf("epoll_ctl error : %d\n", errno);        exit(EXIT_FAILURE);    }    ++cur_fds;  // 即cur_fds = 1;    while (true) {        if ((wait_fds = epoll_wait(epoll_fd, evs, cur_fds, -1)) == -1) {            printf("epoll_wait error : %d\n", errno);            exit(EXIT_FAILURE);        }        for (i = 0; i < wait_fds; ++i) {            if (evs[i].events & EPOLLIN) {                printf("EPOLLIN ...\n");                printf("client get from server ...\n");                memset(recv, 0, sizeof(recv));                n = read(evs[i].data.fd, recv, MAXLINE);                // read错误判断                if (n == 0) {                    printf("recv OK ...\n");                    continue;                } else if (n == -1) {                    printf("recv ERROR ...\n");                    continue;                } else {                    lens = strlen(recv);                    recv[lens] = '\0';                    printf("write to stdout...\n");                    write(STDOUT_FILENO, recv, MAXLINE);                    printf("\n");                }            }            if (evs[i].events & EPOLLOUT) {                printf("EPOLLOUT ...\n");                memset(send, 0, sizeof(send));                if (fgets(send, MAXLINE, fp) == NULL) {                    printf("End ...\n");                    exit(EXIT_FAILURE);                } else {                    lens = strlen(send);                    send[lens - 1] = '\0';                     if (strcmp(send, "q") == 0) {                        printf("Bye ...\n");                        return;                    }                    printf("client send: %s\n", send);                    write(evs[i].data.fd, send, strlen(send));                    // 错误判断                }            }        }    }}void send_and_recv(int conn_fd) {    FILE* fp = stdin;    int lens;    char send[MAXLINE];    char recv[MAXLINE];    fd_set rset;        // select()机制中提供一fd_set的数据结构    FD_ZERO(&rset);    int maxfd = (fileno(fp) > conn_fd ? fileno(fp) : (conn_fd + 1));    int n;    while (true) {        FD_SET(fileno(fp), &rset);        FD_SET(conn_fd, &rset);        if (select(maxfd, &rset, NULL, NULL, NULL) == -1) {            printf("client select error ...\n");            exit(EXIT_FAILURE);        }        if (FD_ISSET(conn_fd, &rset)) {            printf("client get from server ...\n");            memset(recv, 0, sizeof(recv));            n = read(conn_fd, recv, MAXLINE);            if (n == 0) {                printf("recv OK ...\n");                break;                } else if (n == -1) {                    printf("recv ERROR ...\n");                    break;                } else {                    lens = strlen(recv);                    recv[lens] = '\0';                    write(STDOUT_FILENO, recv, MAXLINE);                    printf("\n");                }            }            if (FD_ISSET(fileno(fp), &rset)) {                memset(send, 0, sizeof(send));                if (fgets(send, MAXLINE, fp) == NULL) {                    printf("End ...\n");                    exit(EXIT_FAILURE);                } else {                    lens = strlen(send);                    send[lens - 1] = '\0';                     if (strcmp(send, "q") == 0) {                        printf("Bye ...\n");                        return;                    }                printf("client send: %s\n", send);                write(conn_fd, send, strlen(send));            }        }    }}int main(int argc, char** argv) {    int conn_fd;    struct sockaddr_in servaddr;    if (argc != 2) {        printf("input server ip! \n");        exit(EXIT_FAILURE);    }    if ((conn_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        printf("socket error...\n");        exit(EXIT_FAILURE);    }    bzero(&servaddr, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(SERV_PORT);    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);    if (connect(conn_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {        printf("connect error...\n");        exit(EXIT_FAILURE);    }    if (setnonblocking(conn_fd) == -1) {        printf("set non blocking error : %d ...\n", errno);        exit(EXIT_FAILURE);    }    send_and_recv_epoll(conn_fd);    //send_and_recv(conn_fd);    close(conn_fd);    printf("Exit\n");    return 0;}
原创粉丝点击