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, ¤t_rdfs, NULL, NULL, NULL)<0){ perror("select error.\n"); return RT_ERR; } // 表示有客户端连接 if(FD_ISSET(listenfd, ¤t_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, ¤t_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], ¤t_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
- Linux Select/Epoll注记
- linux select poll epoll
- linux epoll poll select
- Linux epoll服务器、epoll、poll、select优缺点
- Linux下socket(select,epoll)
- Linux select/epoll网络模型
- Linux epoll poll select 详解
- LINUX多路复用select,poll,epoll
- Linux select、poll、epoll解析
- LINUX多路复用select,poll,epoll
- linux效率优于select的epoll模型
- Linux kernel [select poll epoll]区别
- select,poll,epoll区别 分类: Linux/Shell
- Linux kernel [select poll epoll]区别
- linux 网络编程的Epoll Select
- linux 下 select ,poll ,epoll 对比
- linux 内核poll/select/epoll实现剖析
- Linux socket模型(select, poll, epoll)
- Windows Server2008 R2 设置NAT 让Hyper-V连接Internet
- 九度题目1104整除问题
- B-树和B+树的应用:数据搜索和数据库索引
- dfs和bfs
- window环境下安装easy_install
- Linux Select/Epoll注记
- HDU 5531 几何公式
- Firefox 与 sublime text 3 通过LiveReload插件实现前端代码实时预览
- flask 实现上传图片并缩放作为头像
- POJ 1930 Dead Fraction(小数化分数)
- 【USACO5.3.3】Network of Schools
- Spark+Kafka的Direct方式将偏移量发送到Zookeeper的实现
- python标准库学习3-fileinput
- B树、B-树、B+树、B*树 红黑树