Linux IO多路复用之epoll网络编程基本代码

server端:

1#include <unistd.h> 2#include <sys/types.h> /* basic system data types */ 3#include <sys/socket.h> /* basic socket definitions */ 4#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ 5#include <arpa/inet.h> /* inet(3) functions */ 6#include <sys/epoll.h> /* epoll function */ 7#include <fcntl.h> /* nonblocking */ 8#include <sys/resource.h> /*setrlimit */ 9 10#include <stdlib.h> 11#include <errno.h> 12#include <stdio.h> 13#include <string.h> 14 15 16 17#define MAXEPOLLSIZE 10000 18#define MAXLINE 10240 19int handle(int connfd); 20int setnonblocking(int sockfd) 21{ 22 if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { 23 return -1; 24 } 25 return 0; 26} 27 28int main(int argc, char **argv) 29{ 30 int servPort = 6888; 31 int listenq = 1024; 32 33 int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0; 34 struct sockaddr_in servaddr, cliaddr; 35 socklen_t socklen = sizeof(struct sockaddr_in); 36 struct epoll_event ev; 37 struct epoll_event events[MAXEPOLLSIZE]; 38 struct rlimit rt; 39 char buf[MAXLINE]; 40 41 /* 设置每个进程允许打开的最大文件数 */ 42 rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; 43 if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 44 { 45 perror("setrlimit error"); 46 return -1; 47 } 48 49 50 bzero(&servaddr, sizeof(servaddr)); 51 servaddr.sin_family = AF_INET; 52 servaddr.sin_addr.s_addr = htonl (INADDR_ANY); 53 servaddr.sin_port = htons (servPort); 54 55 listenfd = socket(AF_INET, SOCK_STREAM, 0); 56 if (listenfd == -1) { 57 perror("can't create socket file"); 58 return -1; 59 } 60 61 int opt = 1; 62 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 63 64 if (setnonblocking(listenfd) < 0) { 65 perror("setnonblock error"); 66 } 67 68 if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 69 { 70 perror("bind error"); 71 return -1; 72 } 73 if (listen(listenfd, listenq) == -1) 74 { 75 perror("listen error"); 76 return -1; 77 } 78 /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */ 79 kdpfd = epoll_create(MAXEPOLLSIZE); 80 ev.events = EPOLLIN | EPOLLET; 81 ev.data.fd = listenfd; 82 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 83 { 84 fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd); 85 return -1; 86 } 87 curfds = 1; 88 89 printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq); 90 91 for (;;) { 92 /* 等待有事件发生 */ 93 nfds = epoll_wait(kdpfd, events, curfds, -1); 94 if (nfds == -1) 95 { 96 perror("epoll_wait"); 97 continue; 98 } 99 /* 处理所有事件 */ 100 for (n = 0; n < nfds; ++n) 101 { 102 if (events[n].data.fd == listenfd) 103 { 104 connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen); 105 if (connfd < 0) 106 { 107 perror("accept error"); 108 continue; 109 } 110 111 sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 112 printf("%d:%s", ++acceptCount, buf); 113 114 if (curfds >= MAXEPOLLSIZE) { 115 fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE); 116 close(connfd); 117 continue; 118 } 119 if (setnonblocking(connfd) < 0) { 120 perror("setnonblocking error"); 121 } 122 ev.events = EPOLLIN | EPOLLET; 123 ev.data.fd = connfd; 124 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0) 125 { 126 fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno)); 127 return -1; 128 } 129 curfds++; 130 continue; 131 } 132 // 处理客户端请求 133 if (handle(events[n].data.fd) < 0) { 134 epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev); 135 curfds--; 136 137 138 } 139 } 140 } 141 close(listenfd); 142 return 0; 143} 144int handle(int connfd) { 145 int nread; 146 char buf[MAXLINE]; 147 nread = read(connfd, buf, MAXLINE);//读取客户端socket流 148 149 if (nread == 0) { 150 printf("client close the connection\n"); 151 close(connfd); 152 return -1; 153 } 154 if (nread < 0) { 155 perror("read error"); 156 close(connfd); 157 return -1; 158 } 159 write(connfd, buf, nread);//响应客户端 160 return 0; 161}

client端:

1#include <unistd.h> 2#include <sys/types.h> /* basic system data types */ 3#include <sys/socket.h> /* basic socket definitions */ 4#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ 5#include <arpa/inet.h> /* inet(3) functions */ 6#include <sys/select.h> /* select function*/ 7 8#include <stdlib.h> 9#include <errno.h> 10#include <stdio.h> 11#include <string.h> 12 13#define MAXLINE 10240 14#define max(a,b) ((a) > (b) ? (a) : (b)) 15//typedef struct sockaddr SA; 16 17void handle(int sockfd); 18 19int main(int argc, char **argv) 20{ 21 char * servInetAddr = "127.0.0.1"; 22 int servPort = 6888; 23 char buf[MAXLINE]; 24 int connfd; 25 struct sockaddr_in servaddr; 26 27 if (argc == 2) { 28 servInetAddr = argv[1]; 29 } 30 if (argc == 3) { 31 servInetAddr = argv[1]; 32 servPort = atoi(argv[2]); 33 } 34 if (argc > 3) { 35 printf("usage: selectechoclient <IPaddress> <Port>\n"); 36 return -1; 37 } 38 39 connfd = socket(AF_INET, SOCK_STREAM, 0); 40 41 bzero(&servaddr, sizeof(servaddr)); 42 servaddr.sin_family = AF_INET; 43 servaddr.sin_port = htons(servPort); 44 inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr); 45 46 if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { 47 perror("connect error"); 48 return -1; 49 } 50 printf("welcome to selectechoclient\n"); 51 handle(connfd); /* do it all */ 52 close(connfd); 53 printf("exit\n"); 54 exit(0); 55} 56 57 58void handle(int connfd) 59{ 60 FILE* fp = stdin; 61 char sendline[MAXLINE], recvline[MAXLINE]; 62 fd_set rset; 63 FD_ZERO(&rset); 64 int maxfds = max(fileno(fp), connfd) + 1; 65 int nread; 66 for (;;) { 67 FD_SET(fileno(fp), &rset); 68 FD_SET(connfd, &rset); 69 70 if (select(maxfds, &rset, NULL, NULL, NULL) == -1) { 71 perror("select error"); 72 continue; 73 } 74 75 if (FD_ISSET(connfd, &rset)) { 76 //接收到服务器响应 77 nread = read(connfd, recvline, MAXLINE); 78 if (nread == 0) { 79 printf("server close the connection\n"); 80 break; 81 } 82 else if (nread == -1) { 83 perror("read error"); 84 break; 85 } 86 else { 87 //server response 88 write(STDOUT_FILENO, recvline, nread); 89 } 90 } 91 92 if (FD_ISSET(fileno(fp), &rset)) { 93 //标准输入可读 94 if (fgets(sendline, MAXLINE, fp) == NULL) { 95 //eof exit 96 break; 97 } 98 else { 99 write(connfd, sendline, strlen(sendline)); 100 } 101 } 102 103 } 104}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )