日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

socket epoll网络编程实例

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 socket epoll网络编程实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

總結了各個博主的經驗,寫出了簡單的demo,實例為ET模式,轉載請寫明出處,如有寶貴意見請留言。

?

第一版:

服務端:

#include <stdio.h> #include <sys/epoll.h> #include <stdlib.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/resource.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <netdb.h>#define MAXBUF 1024 #define MAXEPOLLSIZE 10000int main(int argc, char *argv[]) {//設置端口if(argc != 2){ printf("請設置端口號!\n");}int port = atoi(argv[1]); int listener, conn_sock, kdpfd, nfds, n, ret, curfds;socklen_t len;struct sockaddr_in server_addr, client_addr;struct epoll_event ev;struct epoll_event pevent[MAXEPOLLSIZE];struct rlimit rt;rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;//設置系統資源,打開最大文件數if (setrlimit(RLIMIT_NOFILE, &rt) == -1){perror("setrlimit");exit(EXIT_FAILURE);}else{printf("設置系統資源參數成功!\n");}//創建socketif( (listener = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket");exit(EXIT_FAILURE);}else{printf("socket 創建成功!\n");}//設置非堵塞if (fcntl(listener, F_SETFL, fcntl(listener, F_GETFL, 0) | O_NONBLOCK) == -1){perror("fcntl");exit(EXIT_FAILURE);}bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);server_addr.sin_addr.s_addr = INADDR_ANY; //0.0.0.0所有地址//綁定if ( bind( listener, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == -1 ){perror("bind");exit(EXIT_FAILURE);}else{printf("IP 地址和端口綁定成功\n");}if (listen(listener, 10) == -1){perror("listen");exit(EXIT_FAILURE);}else{printf("開啟服務成功!\n");}//創建epoll為ET模式kdpfd = epoll_create(MAXEPOLLSIZE);len = sizeof(struct sockaddr_in);ev.events = EPOLLIN | EPOLLET;ev.data.fd = listener;//socket加入epollif( epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0 ){fprintf( stderr, "epoll set insertion error: fd=%d\n", listener );exit(EXIT_FAILURE);}else{printf("監聽 socket 加入 epoll 成功!\n");}//設置延遲和事件個數,事件由累加完成curfds = 1;//int timeout = 10*1000;while(1){//等待有事件發生//nfds = epoll_wait(kdpfd, pevent, curfds, timeout);nfds = epoll_wait(kdpfd, pevent, curfds, -1);if( nfds == -1 ){perror("epoll_wait");break;}else if (nfds == 0){printf("waiting for connecting...\n");continue;}for (n = 0; n < nfds; ++n){if ((pevent[n].events & EPOLLERR) || (pevent[n].events & EPOLLHUP) || (!(pevent[n].events & EPOLLIN))){//此FD上發生錯誤,或者套接字未準備好讀取(那么為什么通知我們?)fprintf (stderr, "epoll error\n");close(pevent[n].data.fd);continue;}else if (pevent[n].data.fd == listener){//我們在監聽套接字上有一個通知,這意味著一個或多個傳入連接while (1){conn_sock = accept(listener, (struct sockaddr*)&client_addr, &len);if( conn_sock == -1 ){if ((errno == EAGAIN) || (errno == EWOULDBLOCK)){//我們已經處理了所有傳入的連接break;}else{perror ("accept error");break;}}//else // printf("有連接來自于: %s:%d, 分配的 socket 為:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), conn_sock);char hbuf[1024], sbuf[1024];if ( 0 == getnameinfo((struct sockaddr*)&client_addr, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV))printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", conn_sock, hbuf, sbuf);if (fcntl(conn_sock, F_SETFL, fcntl(conn_sock, F_GETFL, 0) | O_NONBLOCK) == -1){perror("fcntl");break;}ev.events = EPOLLIN | EPOLLET;ev.data.fd = conn_sock;if( -1 == epoll_ctl( kdpfd, EPOLL_CTL_ADD, conn_sock, &ev)){fprintf(stderr, "把 socket '%d' 加入 epoll 失敗!%s\n", conn_sock, strerror(errno));exit(EXIT_FAILURE);}curfds ++; }continue;}else{if (do_use_fd(pevent[n].data.fd) < 0){printf ("關閉 %d\n", pevent[n].data.fd); epoll_ctl(kdpfd, EPOLL_CTL_DEL, pevent[n].data.fd,&ev);close(pevent[n].data.fd);curfds--;}}}}close(listener);close(kdpfd);return 0; }int do_use_fd(int connfd) {int done = 0;while(1){char buf[MAXBUF + 1];bzero(buf, MAXBUF + 1);int nread;//讀取客戶端socket流nread = recv(connfd, buf, MAXBUF, 0);if (nread == -1){if (errno != EAGAIN){perror ("recv");done = -1;}break;}else if (nread == 0){done = -1;break;}printf("%d接收消息成功:'%s',共%d個字節的數據\n", connfd, buf, nread);//響應客戶端 if ( -1 == send(connfd, buf, strlen(buf), 0))perror ("write");}return done; }

?

第二版:

.h

#ifndef _INITNETWORK_H_ #define _INITNETWORK_H_#include <stdio.h> #include <sys/epoll.h> #include <stdlib.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/resource.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <pthread.h>#define MAXBUF 1024 #define MAXEPOLLSIZE 10000typedef struct SOCKET_EPOLL_PAR{int listener; //socket句柄int port; //socket端口int kdpfd; //epoll句柄int curfds; //socket連接個數socklen_t len; //len = sizeof(struct sockaddr_in);struct epoll_event ev; //epoll 模式int fd; //當前事件struct epoll_event pevent[MAXEPOLLSIZE]; //事件數集合 }SEPAR;static void *thread_conn(void *arg); static void *thread_do_use_fd(void *arg); int init_system_res(); int init_socket(int *listener, int *port); int init_epoll(SEPAR *se_par); void run_network(int port); int close_network(int listener, int kdpfd);#endif

.c

#include "initnetwork.h"void *thread_conn(void *arg) {SEPAR *pse_par = (SEPAR*)arg;struct sockaddr_in client_addr;while (1){ int conn_sock = accept(pse_par->listener, (struct sockaddr*)&client_addr, &(pse_par->len));if( conn_sock == -1 ){if ((errno == EAGAIN) || (errno == EWOULDBLOCK)){//我們已經處理了所有傳入的連接break;}else{perror ("accept error");break;}}char hbuf[1024], sbuf[1024];if ( 0 == getnameinfo((struct sockaddr*)&client_addr, pse_par->len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV))printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", conn_sock, hbuf, sbuf);if (fcntl(conn_sock, F_SETFL, fcntl(conn_sock, F_GETFL, 0) | O_NONBLOCK) == -1){perror("fcntl");break;}pse_par->ev.events = EPOLLIN | EPOLLET;pse_par->ev.data.fd = conn_sock;if( -1 == epoll_ctl( pse_par->kdpfd, EPOLL_CTL_ADD, conn_sock, &(pse_par->ev))){fprintf(stderr, "把 socket '%d' 加入 epoll 失敗!%s\n", conn_sock, strerror(errno));exit(EXIT_FAILURE);}pse_par->curfds++;printf ("conn curfds: %d\n", pse_par->curfds);} }void *thread_do_use_fd(void *arg) {SEPAR *pse_par = (SEPAR*)arg;int done = 0;int conn_fd = pse_par->pevent[pse_par->fd].data.fd;while(1){char buf[MAXBUF + 1];bzero(buf, MAXBUF + 1);int nread;//讀取客戶端socket流nread = recv(conn_fd, buf, MAXBUF, 0);if (nread == -1){if (errno != EAGAIN){perror ("recv");done = -1;}break;}else if (nread == 0){done = -1;break;}printf("%d接收消息成功:'%s',共%d個字節的數據\n", conn_fd, buf, nread);//響應客戶端 if ( -1 == send(conn_fd, buf, strlen(buf), 0))perror ("write");}if (done < 0){printf ("關閉 %d\n", conn_fd);epoll_ctl(pse_par->kdpfd, EPOLL_CTL_DEL, conn_fd,&(pse_par->ev));close(conn_fd);pse_par->curfds--;printf ("close curfds: %d\n", pse_par->curfds);} }int init_system_res() {struct rlimit rt;rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;if (setrlimit(RLIMIT_NOFILE, &rt) == -1){perror("setrlimit");return -1;}elseprintf("設置系統資源參數成功!\n");return 0; }int init_socket(int *listener, int *port) {//創建socketif( (*listener = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket");return -1;}elseprintf("socket 創建成功!\n");//設置非堵塞if (fcntl(*listener, F_SETFL, fcntl(*listener, F_GETFL, 0) | O_NONBLOCK) == -1){perror("fcntl");return -1;}struct sockaddr_in server_addr;bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(*port);server_addr.sin_addr.s_addr = INADDR_ANY; //0.0.0.0所有地址//綁定if (bind( *listener, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == -1 ){perror("bind");return -1;}elseprintf("IP 地址和端口綁定成功\n");//監聽if (listen( *listener, MAXEPOLLSIZE) == -1){perror("listen");return -1;}elseprintf("開啟服務成功!\n");return 0; }int init_epoll(SEPAR *se_par) {//創建epoll為ET模式se_par->kdpfd = epoll_create(MAXEPOLLSIZE);se_par->len = sizeof(struct sockaddr_in);se_par->ev.events = EPOLLIN | EPOLLET;se_par->ev.data.fd = se_par->listener;//socket加入epollif( epoll_ctl(se_par->kdpfd, EPOLL_CTL_ADD, se_par->listener, &(se_par->ev)) < 0 ){fprintf( stderr, "epoll set insertion error: fd=%d\n", se_par->listener );return -1;}elseprintf("監聽 socket 加入 epoll 成功!\n");return 0; }void run_network(int port) {SEPAR se_par;int nfds, n;se_par.port = port;//設置系統資源,打開最大文件數if(init_system_res() == -1)abort();//初始化網絡if (init_socket(&se_par.listener, &se_par.port) == -1)abort();//創建epoll并添加socketif (init_epoll(&se_par) == -1)abort();//設置延遲和事件個數,事件由累加完成se_par.curfds = 1;//int timeout = 10*1000;while(1){//等待有事件發生//nfds = epoll_wait(kdpfd, pevent, curfds, timeout);nfds = epoll_wait(se_par.kdpfd, se_par.pevent, se_par.curfds, -1);if( nfds == -1 ){perror("epoll_wait");break;}else if (nfds == 0){printf("waiting for connecting...\n");continue;}for (n = 0; n < nfds; ++n){if ((se_par.pevent[n].events & EPOLLERR) || (se_par.pevent[n].events & EPOLLHUP) || (!(se_par.pevent[n].events & EPOLLIN))){//此FD上發生錯誤,或者套接字未準備好讀取(那么為什么通知我們?)fprintf (stderr, "epoll error\n");close(se_par.pevent[n].data.fd);continue;}else if (se_par.pevent[n].data.fd == se_par.listener){//我們在監聽套接字上有一個通知,這意味著一個或多個傳入連接 pthread_t tid;int ret = pthread_create(&tid, NULL, thread_conn, (void*)&se_par);if (ret != 0)printf ("創建epoll連接線程出錯!");continue;}else{//處理事件pthread_t tid;se_par.fd = n;int ret = pthread_create(&tid, NULL, thread_do_use_fd, (void*)&se_par);if (ret != 0)printf ("創建epoll事件線程出錯!");}}}if (close_network(se_par.listener, se_par.kdpfd) == -1)abort(); }int close_network(int listener, int kdpfd) {if (close(listener) == -1){perror ("close listener");return -1;}if (close(kdpfd) == -1){perror ("close kdpfd");return -1;}return 0; }

?

?

?

測試客戶端:

/** * socket簡單編程 客戶端* */#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h>#define BUFFSIZE 1024int main(int argc, char *argv[]) {int client_sockfd = 0;int len = 0;struct sockaddr_in server_addr;char buf[BUFFSIZE] = {0};bzero(&server_addr, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");server_addr.sin_port = htons(8080);if((client_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket error!\n");return -1;}if(connect(client_sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0){perror("client error!\n");return -1;}printf("connect success!\n");// len = recv(client_sockfd, buf, BUFFSIZE, 0); // buf[len] = '\0'; // printf("client_buf = %s\n",buf);while(1){printf("Enter string to send:");bzero(buf, sizeof(buf));scanf("%s",buf);if(!strcmp(buf,"quit")){break;}len = send(client_sockfd, buf, strlen(buf), 0);bzero(buf, sizeof(buf));len = recv(client_sockfd, buf, BUFFSIZE, 0);buf[len] = '\0';printf("received: %s\n",buf);}close(client_sockfd);return 0; }

?

總結

以上是生活随笔為你收集整理的socket epoll网络编程实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。