Linux Select/Epoll注记

来源:互联网 发布:华讯网络好吗 编辑:程序博客网 时间:2024/06/08 16:56

Select

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <fcntl.h>#define SERV_PORT 8888#define MAX_LISTEN_QUE 5#define MAX_BUFFER_SIZE 1024#define RT_ERR (-1)#define RT_OK  0
#include "socket_includes.h"int mz_ipv4_tcp_create_socket(void){    int listenfd, sockfd, opt = 1;    struct sockaddr_in server, client;    socklen_t len;    int timep;    int ret;    listenfd = socket(AF_INET, SOCK_STREAM, 0);    if(listenfd < 0){        perror("Create socket fail.");        return -1;    }     if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){        perror("Error, set socket reuse addr failed");          return -1;    }    bzero(&server, sizeof(server));    server.sin_family = AF_INET;    server.sin_port   = htons(SERV_PORT);    server.sin_addr.s_addr  = htonl(INADDR_ANY); //本地所有网卡    len = sizeof(struct sockaddr);    if(bind(listenfd, (struct sockaddr *)&server, len)<0){              perror("bind error.");        return -1;    }    listen(listenfd, MAX_LISTEN_QUE);    return listenfd;}int main(int argc, char *argv[]){    int listenfd, sockfd;    struct sockaddr_in server, client;    socklen_t len;    int bytes =0 ;    fd_set global_rdfs,current_rdfs;        int maxfd;      int i;    char buf[MAX_BUFFER_SIZE];    // 连接的client数组。一个进程fd一般最大个数为1024    int client_fd[FD_SETSIZE];    len = sizeof(struct sockaddr_in);    printf("FD_SETSIZE=%d\n", FD_SETSIZE);    // 创建和绑定sever socket对应的fd    listenfd = mz_ipv4_tcp_create_socket();    FD_ZERO(&global_rdfs);    // 监听客户端连接事件    FD_SET(listenfd, &global_rdfs);    // listenfd默认从3开始,0-2分别表示标准输入、标准输出、错误输出    maxfd = listenfd;    //     for(i = 0; i < FD_SETSIZE; i++ ) {        client_fd[i] = -1;    }    while(1) {        current_rdfs = global_rdfs;        // 阻塞,当有有消息或者超时才往下执行        if(select(maxfd + 1, &current_rdfs, NULL, NULL, NULL)<0){            perror("select error.\n");            return RT_ERR;        }        // 表示有客户端连接        if(FD_ISSET(listenfd, &current_rdfs)){            if((sockfd = accept(listenfd, (struct sockaddr*)&client, (socklen_t*)&len))<0){                perror("accept error.\n");                return RT_ERR;            }            printf("IP: 0x%x, Port:%d\n", ntohl(client.sin_addr.s_addr), ntohs(client.sin_port));            printf("sockfd:%d\n", sockfd);            // 清除current_rdfs中listenfd标记            FD_CLR(listenfd, &current_rdfs);            maxfd = maxfd > sockfd ? maxfd :sockfd;            // 监听socket的事件            FD_SET(sockfd, &global_rdfs);            for(i = 0; i < maxfd; i++){                if(-1 == client_fd[i]){                    client_fd[i] = sockfd;                    break;                }            }        }        for(i = 0; i <= maxfd; i++){            if(-1 == client_fd[i]){                continue;            }               // 因为上面清除listenfd标记,所以如果有标记,那么都是sockfd标记            if(FD_ISSET(client_fd[i], &current_rdfs)){                printf("read socket:%d\n", client_fd[i]);                // 从客户端读取数据                bytes = recv(client_fd[i], buf, MAX_BUFFER_SIZE, 0);                if(bytes < 0){                    perror("recv error.\n");                    return RT_ERR;                }                // 表示客户端关闭连接                if(bytes == 0){                    // 不再监听断开的sockfd                    FD_CLR(client_fd[i], &global_rdfs);                    close(client_fd[i]);                    client_fd[i] = -1;                    continue;                }                printf("buf:%s\n", buf);                // 发送数据给客户端                send(client_fd[i], buf, strlen(buf), 0);            }        }    }}

Epoll

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <fcntl.h>#define SERV_PORT 8888#define MAX_LISTEN_QUE 5#define MAX_BUFFER_SIZE 1024#define RT_ERR (-1)#define RT_OK  0#define MAX_EVENTS 500
#include "socket_includes.h"#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>#include <errno.h>int mz_ipv4_tcp_create_socket(void){    int listenfd, sockfd, opt = 1;    struct sockaddr_in server, client;    socklen_t len;    int timep;    int ret;    listenfd = socket(AF_INET, SOCK_STREAM, 0);    if(listenfd < 0){        perror("Create socket fail.");        return -1;    }     if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){        perror("Error, set socket reuse addr failed");          return -1;    }    bzero(&server, sizeof(server));    server.sin_family = AF_INET;    server.sin_port   = htons(SERV_PORT);    server.sin_addr.s_addr  = htonl(INADDR_ANY);    len = sizeof(struct sockaddr);    if(bind(listenfd, (struct sockaddr *)&server, len)<0){              perror("bind error.");        return -1;    }    listen(listenfd, MAX_LISTEN_QUE);    return listenfd;}int mz_process_data(int sockfd){    int bytes;    char buf[100];    char *s = buf;    char flag = 1;    int len;    while(flag){        bytes = recv(sockfd, s, 5, 0);        if(bytes < 0){            // 这种捕获错误做法?            if(errno == EAGAIN){                printf("no data.\n");                char * mesg = strerror(errno);                break;            }            perror("recv err:");            return -1;        }        //  关闭连接        if(bytes == 0){            return -2;        }        if(bytes == 5){            flag = 1;        }else {            flag = 0;        }        s += bytes;        len += bytes;        printf("bytes:%d\n", bytes);        //sleep(2);    }    printf("buf:%s\n", buf);    send(sockfd, buf, len, 0);    return 0;}int main(int argc, char *argv[]){    int listenfd, sockfd;    int epollfd, fds;    struct epoll_event ev, events[MAX_EVENTS];    int i, rv;    struct sockaddr_in client;    int len;    len = sizeof(struct sockaddr_in);    epollfd = epoll_create(MAX_EVENTS);    if(epollfd < 0){        perror("epoll_create err:");        return -1;    }    listenfd = mz_ipv4_tcp_create_socket();    // listenfd设置为非阻塞的?    fcntl(listenfd, F_SETFL, O_NONBLOCK);    ev.data.fd = listenfd;    ev.events = EPOLLIN; //监听输入事件    // 添加listenfd的EPOLLIN    rv = epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);    if(rv < 0){        perror("epoll_ctl err:");        return -1;    }    while(1){        //time_out        fds = epoll_wait(epollfd, events, MAX_EVENTS, -1);        if(fds < 0){            perror("epoll_wait err:");            return -1;        }        for(i = 0; i < fds; i++){            // 有客户端连接            if(events[i].data.fd == listenfd){                sockfd = accept(listenfd, (struct sockaddr *)&client, &len);                if(sockfd < 0){                    perror("accept err:");                    continue;                }                ev.data.fd = sockfd;                ev.events = EPOLLIN | EPOLLET;                // 添加sockfd的EPOLLIN | EPOLLET事件                epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev);                continue;            }else {                 rv = mz_process_data(events[i].data.fd);                // 客户端关闭                if(rv == -2){                    // 取消监听                    epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &ev);                    // 关闭连接                    close(events[i].data.fd);                    continue;                }            }        }    }}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 三星a9屏幕漏液怎么办 小米note后面玻璃碎了怎么办 换手机微信钱包怎么办 内外屏一体手机屏幕碎了怎么办 苹果手机显示屏坏了怎么办 华为手机屏裂了怎么办 乐视手机屏坏了怎么办 红米手机触屏失灵怎么办 小米4排线断了怎么办 红米3x屏幕难点怎么办 华为p7屏幕不亮怎么办 红米5外屏碎了怎么办 小米电视碎屏了怎么办 oppo手机第二屏幕打不开怎么办 红米note3屏幕裂了怎么办 小米3屏幕烂了怎么办 苹果x屏幕触屏不灵怎么办 票买好了身份证丢了怎么办 广发信用卡身份证到期了怎么办 人在外地身份证丢了怎么办 人在国外身份证丢了怎么办 身份证丢了户口本不在怎么办 在北京身份证过期了怎么办 没社保卡怎么办厦门健康卡 扬州市民卡丢了怎么办 扬州市民卡坏了怎么办 重庆社保卡坏了怎么办 社保卡丢了看病怎么办 社保卡丢了买药怎么办 常州社保卡丢了怎么办 深圳社保卡掉了怎么办 上海医保卡丢了怎么办 户口转到西安后医保怎么办 上海医保卡掉了怎么办 上海医保本丢了怎么办? 新版医保卡丢了怎么办 武汉社保卡掉了怎么办 职工社保卡丢了怎么办 杭州社保卡丢了怎么办 农村医疗卡丢了怎么办 陕西省医保卡丢了怎么办