epoll编程,困扰了我6年的问题!求讨论。

用epoll et模式写一个socket服务器,2010年我就写过一个,但总是会不定时间“停止响应”:telnet能连接上,但不能发送数据也不能收取到数据,当年是这个问题。

后来换python还是没能解决。
多年来反反复复尝试,都没能写出一个稳定socket服务,实在是一大人生憾事啊。

最近想写一个socket转发服务:客户端连接上来,socket服务开启线程链接到启动参数指定的服务器,然后转发二者的通讯数据,不做任何的修改。

其作用:
1隐藏你的真实服务器,起到保护作用
2代理加速作用
3研究用途,可以获得其它某些程序的通讯内容。

现在能长时间运行不出内存问题,但是会出errno=24,即too many open files,/proc/pid/fd下会有好几万个fd。
但netstat看到的却很少。我对所有socket打开和关闭做了记录,对记录进行统计,发现打开和关闭次数是相等的。

** 最初我只是close(fd),
现在我改成了shutdown + close**

问题依旧。

我用的多线程,每连接一个客户端,开启一个线程a,此线程a先去连接服务器端。
连接成功,开启线程b,b去去读客户端数据,收到数据,则直接发送到服务器端。
线程a读取服务器端,收到数据则发送到客户端。
两个线程的参数都是同一个结构体s,s中有服务器、客户端的连接fd。还有二个连接的连接状态,以便一方断开另外一方也断开。

到底怎样才能保证fd关闭且移除?

谢谢!

1个回答

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Linux 网络编程 epoll中的EPOLLIN EPOLLOUT如何触发

代码很长只截取关键部分 //服务器端 #include<sys/socket.h> #include<netinet/in.h> #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<cassert> #include<sys/epoll.h> #include"locker.h" #include"threadpool.h" #include"http_conn.h" #include"http_conn.cpp" extern void addfd(int epollfd,int fd,bool one_shot); extern void removefd(int epollfd,int fd); #define MAX_FD 65536 #define MAX_EVENT_NUMBER 10000 void addsig(int sig,void(handler)(int),bool restart=true) { struct sigaction sa; memset(&sa,'\0',sizeof(sa)); sa.sa_handler=handler; if(restart) { sa.sa_flags|=SA_RESTART; } sigfillset(&sa.sa_mask); assert(sigaction(sig,&sa,NULL)!=-1); } void show_error(int connfd,const char* info) { printf("%s",info); send(connfd,info,strlen(info),0); close(connfd); } int main(int argc,char* argv[]) { if(argc<2) { printf("usage: %s ip_address port_number\n",basename(argv[0])); return 1; } const char* ip=argv[1]; int port=atoi(argv[2]); addsig(SIGPIPE,SIG_IGN); threadpool<http_conn>* pool=NULL; pool=new threadpool<http_conn>(3); http_conn* users=new http_conn[MAX_FD]; assert(users); int user_count=0; int listenfd=socket(PF_INET,SOCK_STREAM,0); assert(listenfd>=0); struct linger tmp={1,0}; setsockopt(listenfd,SOL_SOCKET,SO_LINGER,&tmp,sizeof(tmp)); int ret=0; struct sockaddr_in address; bzero(&address,sizeof(address)); address.sin_family=AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port=htons(port); ret=bind(listenfd,(struct sockaddr*)&address,sizeof(address)); assert(ret>=0); ret=listen(listenfd,5); assert(ret>=0); epoll_event events[MAX_EVENT_NUMBER]; int epollfd=epoll_create(5); assert(epollfd!=-1); addfd(epollfd,listenfd,false); http_conn::m_epollfd=epollfd; while(1) { int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1); printf("number is %d\n",number); if((number<0)&&(errno!=EINTR)) { printf("epoll failure\n"); break; } for(int i=0;i<number;i++) { int sockfd=events[i].data.fd; if(sockfd==listenfd) { struct sockaddr_in client_address; socklen_t client_addrlength=sizeof(client_address); int connfd=accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength); if(connfd<0) { printf("errno is: %d\n",errno); continue; } if(http_conn::m_user_count>=MAX_FD) { show_error(connfd,"Internal sever busy"); continue; } printf("running the init(connfd,client_address)"\n); users[connfd].init(connfd,client_address); } else if(events[i].events&(EPOLLRDHUP|EPOLLHUP|EPOLLERR)) { users[sockfd].close_conn(); } else if(events[i].events&EPOLLIN) { if(users[sockfd].read()) { pool->append(users+sockfd); } else { users[sockfd].close_conn(); } } else if(events[i].events&EPOLLOUT) { if(!users[sockfd].write()) { users[sockfd].close_conn(); } } } } close(epollfd); close(listenfd); delete [] users; delete pool; return 0; } 以上是服务器端的主程序 思路是epoll_wait接收到连接就为连接创建一个users存储然后等待后续的操作 但后面EPOLLIN 和EPOLLOUT永远都没法触发 不清楚该怎么触发 另一端写了服务器压力测试程序 和以上代码类似 就是循环创建socket对象然后connect()服务器 但我本意想两端互相发送数据 可connect()后服务器收到创建一个user 继续循环等待 但压力测试程序也在创建完对象后陷入循环等待服务器端的操作 请问该如何触发EPOLLIN和EPOLLOUT信号 以下是压力测试程序关键代码 #include<stdlib.h> #include<stdio.h> #include<assert.h> #include<unistd.h> #include<sys/types.h> #include<sys/epoll.h> #include<fcntl.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<string.h> static const char* request = "GET http://localhost/index.html HTTP/1.1\r\nConnection: keep-alive\r\n\r\nxxxxxxxxxx"; int setnonblocking(int fd) { int old_option=fcntl(fd,F_GETFL); int new_option=old_option|O_NONBLOCK; fcntl(fd,F_SETFL,new_option); return old_option; } void addfd(int epollfd,int fd) { epoll_event event; event.data.fd=fd; event.events=EPOLLIN|EPOLLET|EPOLLRDHUP; epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); setnonblocking(fd); } bool write_nbytes(int sockfd,const char* buffer,int len) { int byters_write=0; printf("write out %d bytes to socket %d\n",len,sockfd); while(1) { bytes_write=send(sockfd,buffer,len,0); if(bytes_write==-1) { return false; } else if(bytes_write==0) { return false; } len-=bytes_write; buffer=buffer+bytes_write; if(len<=0) { return true; } } } bool read_once(int sockfd,char* buffer,int len) { int bytes_read=0; memset(buffer,'\0',len); bytes_read=recv(sockfd,buffer,len,0); if(bytes_read==-1) { return false; } else if(bytes_read==0) { return false; } printf("read in %d bytes from socket %d with content: %s\n",bytes_read,sockfd,buffer); return true; } void start_conn(int epoll_fd,int num,const char* ip,int port) { int ret=0; struct sockaddr_in address; bzero(&address,sizeof(address)); address.sin_family=AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port=htons(port); for(int i=0;i<num;++i) { sllep(1); int sockfd=socket(PF_INET,SOCK_STREAM,0); printf("create 1 sock\n"); if(sockfd<0) { continue; } if(connect(sockfd,(struct sockaddr*)&address,sizeof(address))==0) { printf("build connection %d\n",i); addfd(epoll_fd,sockfd); } } } void close_conn(int epoll_fd,int sockfd) { epoll_ctl(epoll_fd,EPOLL_CTL_DEL,sockfd,0); close(sockfd); } int main(int argc,char* argv[]) { assert(argc==4); int epoll_fd=epoll_create(100); start_conn(epoll_fd,atoi(argv[3]),argv[1],atoi(argv[2])); epoll_event events[10000]; char buffer[2048]; while(1) { int fds=epoll_wait(epoll_fd,events,10000,2000); for(int i=0;i<fds;i++) { int sockfd=events[i].data.fd; if(event[i].events&EPOLLIN) { if(!read_once(sockfd,buffer,2048)); { close_conn(epoll_fd,sockfd); } struct epoll_event event; event.events=EPOLLOUT|EPOLLET|EPOLLERR; event.data.fd=sockfd; epoll_ctl(epoll_fd,EPOLL_CTL_MOD,sockfd,&event); } else if(events[i].events&EPOLLOUT) { if(!write_nbytes(sockfd,request,strlen(request))) { close_conn(epoll_fd,sockfd); } struct epoll_event event; event.events=EPOLLIN|EPOLLET|EPOLLERR; event.data.fd=sockfd; epoll_ctl(epoll_fd,EPOLL_CTL_MOD,sockfd,&event); } else if(events[i].events&EPOLLERR) { close_conn(epoll_fd,sockfd); } } } }

有关epoll的具体应用问题

服务端采用epoll ET模式,当有请求过来,epoll_wait会告知有数据可读,因此进行 读操作(ET下,这里是一次性读完吗?,如果读取数据很大,那岂不是效率低了?), 同时进行数据处理; 我不明白的是,应该在什么地方关注该fd的写事件---即哪里写 epoll_ctl(epfd, EPOLL_OUT, fd, events) ? epoll的事件触发,EPOLL_IN比较懂,有数据传入,epoll_wait告知; 那EPOLL_OUT呢,我明白在发送缓冲区可写时,会触发EPOLL_OUT,但是这怎么跟服务器的设计联系起来呢?

关于epoll返回值的问题

epoll\_wait返回值是就绪描述符的数量n,那么下来应该遍历0~maxevents选出这n个描述符,而我看例子代码中是直接遍历0~n的。请指教

关于epoll的问题,发送缓冲区以及接受缓冲区?

本人刚学习epoll,向论坛大神问几个问题 本人理解,ET只有在文件描述符未就绪变为就绪时才会重新通过内核来告知,导致每一次的读取必须将缓冲区内数据读完,即处理完该事件 但是我们自己设定的用户空间缓冲区buf是有大小的,假如小于sockfd通告窗口大小,还是说我们会一般将用户空间的buf大小就写成和通告的窗口大小写成一致,则不存在,一次无法将缓冲区读完的情况发生 以下是tcp回射程序的部分 ``` else if(events[i].events&EPOLLIN) { if((sockfd=events[i].data.fd)<0) continue; while(rs) { if((n=read(sockfd,buf,MAXLINE))<0) { if(errno==ECONNRESET||errno=EAGAIN) { close(sockfd); events[i].data.fd=-1; } else if(n==0) { close(sockfd); events[i].data.fd=-1; } } if(n==sizeof(buf)) rs=1; else rs=0; } ev.data.fd=sockfd; ev.events=EPOLLOUT|EPOLLET; epoll_ctl(efd,EPOLL_CTL_MOD,sockfd,&ev); } ``` 如何一直读sockfd,这是本人自己理解的 epoll但由于一直没有用epoll将该sockfd改成写,无法将buf内的数据写到sockfd,如何改正,或者如何正确的写出epoll函数, 我在网上找了很多种实现epoll的都并没有持续读直到无法读取那一部分的代码。一直不理解epoll如何实现这一过程,同理write过程也有这样一个问题,(若没写完buf内的内容必须持续写),但后面写的部分由于无法读取会覆盖前面写的部分,可能问题有些混乱,谢谢各位大神

Linux网络编程 epoll中EPOLLIN EPOLLOUT信号无法触发

比如 if(events[i].events&EPOLLIN) { int bytes_read=read(m_sockfd,read_buf,READ_BUFFER_SIZE); } 这样会触发EPOLLIN 但如果把read()封装到比如service类的sread()函数中 if(events[i].events&EPOLLIN) { service.sread() } 便不会触发EPOLLIN事件 请问问题出在哪 我使用同一个测试程序 第一种写法就可以触发第二种就不行

c++,epoll,线程池,求解

主要问题: 客户端 与服务器端进行通信(传送一个字符串)当服务器端检测到epollin事件到来时,创建一个任务,加入到任务队列,相应的线程去处理任务。问题来了,为什么我的客户端与服务器只进行一次字符串的传送,服务器端会添加多个任务(300左右个)正常的话,应该是一个任务,所有的线程去抢这个任务,谁拿到任务了谁去执行,然后剩下的线程进行休眠。。。。。本人学生, 才接触这一块,希望大家帮帮忙。。。。 ``` 客户端 # include <iostream> # include <algorithm> # include <stdio.h> # include <string> # include <cstring> # include <cstdlib> # include <unistd.h> # include <sys/types.h> # include <sys/socket.h> # include <netinet/in.h> # include <arpa/inet.h> using namespace std ; # define ERR_EXIT(err) \ do \ { \ perror(err) ; \ exit(EXIT_FAILURE) ; \ \ }while(0) \ int main () { int res = 0 ; char buf[1024] ; memset(buf, 0, sizeof(buf)) ; int sockfd = socket(PF_INET, SOCK_STREAM, 0) ; if(sockfd < 0) ERR_EXIT("socket err") ; struct sockaddr_in cltaddr ; memset(&cltaddr, 0, sizeof(cltaddr)) ; cltaddr.sin_family = AF_INET ; cltaddr.sin_port = htons(8001) ; cltaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ;; res = connect(sockfd, (struct sockaddr *)&cltaddr, sizeof(cltaddr)) ; if(res < 0) ERR_EXIT("connect err") ; cin >> buf ; cout << buf << endl ; while(strcmp("exit", buf) != 0) { write(sockfd, buf, sizeof(buf)) ; memset(buf, '\0', sizeof(buf)) ; cin >> buf ; } close(sockfd) ; return 0 ; } ``` ``` 线程池 #ifndef _CTHREADPOLL_H_ #define _CTHREADPOLL_H_ # include <unistd.h> # include <stdlib.h> # include <fcntl.h> # include <arpa/inet.h> # include <sys/stat.h> # include <signal.h> # include <sys/types.h> # include <iostream> # include <sys/socket.h> # include <sys/socket.h> # include <iomanip> # include <string.h> # include <string> # include <errno.h> # include <vector> # include <sys/wait.h> # include <pthread.h> # include <sys/epoll.h> # include <algorithm> using namespace std ; class CTask { public: CTask(){} ; // 无参构造函数 CTask(string taskName) // 有参构造函数 { this->m_strTaskName = taskName ; this->m_ptrData = NULL ; } public: virtual int PerformTask() = 0 ; // 执行任务的接口 void SetData(void *data) // 设置数据 { this->m_ptrData = data ; } protected: void *m_ptrData ; string m_strTaskName ; } ; class CThreadPoll { public: CThreadPoll(int threadNum = 10) ; // 有默认值的构造函数 public: int AddTack(CTask *task) ; // 添加任务到任务队列中 int getTaskSize() ; // 获取当前任务队列的数量 int StopAll() ; // 使线程池中的线程退出 protected: int CreatepThread() ; // 创建线程池中的线程 static void *ThreadCallBack (void * arg) ; // 线程回调函数 private: pthread_t *m_Thread_id ; // 线程id int m_iThreadNum ; // 线程池中的线程数量 static bool shutdown ; // 线程退出标志 static pthread_mutex_t m_pthreadMutex ; // poxsi线程锁 static pthread_cond_t m_pthreadCond ; // 条件等待变量 static vector<CTask *> m_vecTaskList ; // 任务列表 } ; #endif # include "CThreadpool.h" /************************************************************************/ bool CThreadPoll::shutdown = false ; // 线程退出标志 vector<CTask *> CThreadPoll::m_vecTaskList ; // 任务列表 pthread_mutex_t CThreadPoll::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER ; // poxsi线程锁 pthread_cond_t CThreadPoll::m_pthreadCond = PTHREAD_COND_INITIALIZER ; // 条件等待变量 int CThreadPoll::CreatepThread() { m_Thread_id = new pthread_t[m_iThreadNum] ; for(int i = 0; i < m_iThreadNum; i ++) { pthread_create(&m_Thread_id[i], NULL, ThreadCallBack, NULL); } return 0 ; } CThreadPoll::CThreadPoll(int threadNum) // 有默认值的构造函数 { this->m_iThreadNum = (pthread_t)threadNum ; CreatepThread() ; } void *CThreadPoll::ThreadCallBack (void *arg) { pthread_t tid = pthread_self() ; while(1) { pthread_mutex_lock(&m_pthreadMutex) ; cout << "tid is : " << tid << endl ; cout << "size is :" << m_vecTaskList.size() << endl ; while(m_vecTaskList.size() == 0 && !shutdown) { pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex) ; } cout << "tid is1111 : " << tid << endl ; cout << "size is11111 :" << m_vecTaskList.size() << endl ; if(shutdown) { pthread_mutex_unlock(&m_pthreadMutex) ; pthread_exit(NULL) ; } vector<CTask *>::iterator iter = m_vecTaskList.begin() ; CTask *temp = NULL ; if(iter != m_vecTaskList.end()) { temp = *iter ; cout << "delete ..." << endl ; m_vecTaskList.erase(iter) ; } temp->PerformTask() ; pthread_mutex_unlock(&m_pthreadMutex) ; // sleep(2) ; } return NULL ; } int CThreadPoll::AddTack(CTask *task) { pthread_mutex_lock(&m_pthreadMutex) ; this->m_vecTaskList.push_back(task) ; pthread_mutex_unlock(&m_pthreadMutex) ; pthread_cond_signal(&m_pthreadCond) ; // pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex) ; return 0 ; } int CThreadPoll::getTaskSize() { return this->m_vecTaskList.size() ; } int CThreadPoll::StopAll() { if(shutdown) { return -1 ; } // 把退出标记设置为true,唤醒所有等待的线程让它们退出 shutdown = true ; pthread_cond_broadcast(&m_pthreadCond) ; // 等待所有线程退出, 不然就成了僵尸线程了 for(int i = 0; i < m_iThreadNum; i ++) { pthread_join(m_Thread_id[i], NULL) ; } //释放掉tid所占用的内存空间 delete [] m_Thread_id ; //销毁互斥锁,和条件变量 pthread_cond_destroy(&m_pthreadCond) ; pthread_mutex_destroy(&m_pthreadMutex) ; return 0 ; } ``` ``` 测试 # include "CThreadpool.cpp" # include "mysqlbak.cpp" # include <unistd.h> # include <stdlib.h> # include <fcntl.h> # include <arpa/inet.h> # include <sys/stat.h> # include <signal.h> # include <sys/types.h> # include <iostream> # include <sys/socket.h> # include <sys/socket.h> # include <iomanip> # include <string.h> # include <string> # include <errno.h> # include <vector> # include <sys/wait.h> # include <pthread.h> # include <sys/epoll.h> # include <algorithm> using namespace std ; typedef vector<struct epoll_event> EventList ; /*typedef struct _Packet { int len ; char buffsize[1024] ; } PACKET ;*/ struct INFO { int uid ; char name[20] ; char sex[10] ; unsigned int age ; unsigned int score ; } ; class WPTask : public CTask { public: WPTask(){} ; public: int PerformTask() { int ret = 0 ; char str[1024] ; struct INFO person ; int connfd = this->m_Connfd ; ret = read(connfd, str, sizeof(str)) ; if(ret == 0) { cout << "client close." << endl ; epoll_ctl(epollfd, EPOLL_CTL_DEL, connfd, &event) ; return -1 ; } cout << str << endl ; // cout << person.uid << " " << person.name << " " << person.sex << // " " << person.age << " " << person.score << endl ; /* ret = query_db(this->m_Mysql) ; if(ret == 0) { cout << "query err:" << endl ; } */ return 0 ; } void SetConnectFd(int connfd) { this->m_Connfd = connfd ; } void SetDatabaseFd(MYSQL mysql) { this->m_Mysql = mysql ; } protected: MYSQL m_Mysql ; int m_Connfd ; public: int epollfd ; struct epoll_event event ; } ; int main () { MYSQL mysql ; int res = login_db(mysql) ; if(res == -1) cout << "login_db err" << endl ; signal(SIGPIPE, SIG_IGN) ; signal(SIGCHLD, SIG_IGN) ; struct sockaddr_in srvaddr ; memset(&srvaddr, 0, sizeof(srvaddr)) ; srvaddr.sin_port = ntohs(8001) ; srvaddr.sin_family = AF_INET ; srvaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ; int idlefd = open("dev/null", O_RDONLY | O_CLOEXEC) ; int listenfd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_TCP) ; if(listenfd == -1) cout << "socket failure." << endl ; int on = 1 ; if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) cout << "setsockopt failure." << endl ; if(bind(listenfd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) == -1) cout << "bind failure." << endl ; if(listen(listenfd, SOMAXCONN) == -1) cout << "listen failure." << endl ; CThreadPoll pthread(10) ; int nready, connfd ; int nontimeout = -1 ; EventList events(16) ; struct epoll_event event ; event.events = EPOLLIN ; event.data.fd = listenfd ; int epollfd = epoll_create1(EPOLL_CLOEXEC) ; epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event) ; struct sockaddr_in peeraddr ; socklen_t peerlen = sizeof(peerlen) ; while(1) { nready = epoll_wait(epollfd, &*events.begin(), static_cast<int>(events.size()), -1) ; if(nready == -1) { if(errno == EINTR) { continue ; } return -1 ; } if(nready == 0) { continue ; } if((size_t)nready == events.size()) { events.resize(events.size() * 2) ; } for(int i = 0; i < nready; i ++) { if(events[i].data.fd == listenfd) { if((connfd = accept4(listenfd, (struct sockaddr *)&peeraddr, &peerlen, SOCK_NONBLOCK | SOCK_CLOEXEC)) == -1) { if(errno == EMFILE) { close(idlefd) ; idlefd = accept(listenfd, NULL, NULL) ; close(idlefd) ; idlefd = open("dev/null", O_RDONLY | O_CLOEXEC) ; continue ; } return -1 ; } cout << "ip:" << inet_ntoa(peeraddr.sin_addr) << endl ; cout << "port:" << ntohl(peeraddr.sin_port) << endl ; event.events = EPOLLIN ; event.data.fd = connfd ; epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event) ; } else if(events[i].events & EPOLLIN) { connfd = events[i].data.fd ; if(connfd == 0) continue ; WPTask *task = new WPTask ; task->epollfd = epollfd ; task->event = events[i] ; task->SetDatabaseFd(mysql) ; task->SetConnectFd(connfd) ; cout << "renwu1" << endl ; // sleep(3) ; pthread.AddTack(task) ; } } } return 0 ; } ``` ![图片说明](https://img-ask.csdn.net/upload/201612/14/1481718038_751898.png) 附上图片: 此图片为客户端与服务器进行一次通信,服务器端建立了N个任务。。。。无语了。。。 如有能很好解决的人 麻烦您有时间的时候加下我的qq:712102032,本人不总玩csdn如能解决,必有重谢。 改成ET貌似可以了,但是。。。我的本意是LT, ET与LT的区别在哪里呢?

golang:以epoll / poll / select方式使用多个客户端/服务器UDP套接字

<div class="post-text" itemprop="text"> <p>So I want to do some experiments with c500K ("problem of having 500K concurrent connections") in Golang, and <code>net.ListenUDP</code> (and its equivalent client connection part) started in 500K goroutines in a single process is not looking like a way to achieve it.</p> <p>What is the "common" pattern on writing multiple socket listeners/clients in Golang using poll/select-like model?</p> </div>

Linux下epoll并发数量达到1987个后涨不上去

Linux下epoll并发数量达到1987个后涨不上去(达到1987个链接后,无法接受新链接,并非最大开文件句柄限制所导致) 我在linux下写来一个简单的epoll server程序,在局域网中另一台windows计算机采用多线程的形式链接server,但是大概epoll链接了1987个套接字后,再也不能增加新链接了(并非最大文件句柄数量所限制),不清楚所什么原因,跪求解答,谢谢各位好心人。 server代码: #include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <sys/epoll.h> /* epoll function */ #include <fcntl.h> /* nonblocking */ #include <sys/resource.h> /*setrlimit */ #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #define MAXEPOLLSIZE 10000 #define MAXLINE 10240 int handle(int connfd); int setnonblocking(int sockfd) { if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { return -1; } return 0; } int main(int argc, char **argv) { int servPort = 6888; int listenq = 1024; int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0; struct sockaddr_in servaddr, cliaddr; socklen_t socklen = sizeof(struct sockaddr_in); struct epoll_event ev; struct epoll_event events[MAXEPOLLSIZE]; struct rlimit rt; char buf[MAXLINE]; /* 设置每个进程允许打开的最大文件数 */ rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; if (setrlimit(RLIMIT_NOFILE, &rt) == -1) { perror("setrlimit error"); return -1; } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons (servPort); listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror("can't create socket file"); return -1; } int opt = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (setnonblocking(listenfd) < 0) { perror("setnonblock error"); } if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) { perror("bind error"); return -1; } if (listen(listenfd, listenq) == -1) { perror("listen error"); return -1; } /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */ kdpfd = epoll_create(MAXEPOLLSIZE); ev.events = EPOLLIN | EPOLLET; ev.data.fd = listenfd; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd); return -1; } curfds = 1; printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq); for (;;) { /* 等待有事件发生 */ nfds = epoll_wait(kdpfd, events, curfds, -1); if (nfds == -1) { perror("epoll_wait"); continue; } /* 处理所有事件 */ for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listenfd) { connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen); if (connfd < 0) { perror("accept error"); continue; } sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); printf("%d:%s", ++acceptCount, buf); if (curfds >= MAXEPOLLSIZE) { fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE); close(connfd); continue; } if (setnonblocking(connfd) < 0) { perror("setnonblocking error"); } ev.events = EPOLLIN | EPOLLET; ev.data.fd = connfd; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0) { fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno)); return -1; } curfds++; printf("%d\n", curfds); continue; } // 处理客户端请求 if (handle(events[n].data.fd) < 0) { epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev); curfds--; } } } close(listenfd); return 0; } int handle(int connfd) { int nread; char buf[MAXLINE]; nread = read(connfd, buf, MAXLINE);//读取客户端socket流 if (nread == 0) { printf("client close the connection\n"); close(connfd); return -1; } if (nread < 0) { perror("read error"); close(connfd); return -1; } write(connfd, buf, nread);//响应客户端 return 0; }

linux如何采用epoll模型?就是我要改哪个地方才可以用这种模型了呢~

我在网上搜,都是说这个模型的实现原理,还说有三个参数但是这东西到底怎么用啊。我现在有一个游戏项目,前后端(java websocket)两种服务器,,中间nginx负载,我需要怎么捣鼓,才可以用上这个epoll模型。 是在内核的什么文件里加个什么代码吗,还是要在代码里配置什么的~求大佬解惑~

linux epoll_wait 监听管道读写事情,为什么管道退出,仍有事件发生

//通过epoll监控管道的读端 #include <stdio.h> #include <unistd.h> #include <syspes.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/epoll.h> #include <string.h> int main() { //管道 int fd[2]; pipe(fd); //创建子进程 pid_t pid = fork(); if(pid == 0){ //子进程 //子进程写dd close(fd[0]);//关闭读端 char buf[12]={0}; buf[10]='\n'; char ch = 'A'; while(1){ memset(buf,ch,10);//将字符串设置为AAAAAAAAAA ch++; write(fd[1],buf,strlen(buf)); sleep(3); break; } }else{ //父进程读 close(fd[1]);//关闭写端 //--创建根节点 int epfd = epoll_create(1); //--加入监听节点 struct epoll_event ev,epv; ev.data.fd = fd[0]; //ev.events = EPOLLIN|EPOLLET;//添加边缘触发模式 ev.events = EPOLLIN;//水平触发 epoll_ctl(epfd,EPOLL_CTL_ADD,fd[0],&ev);//上树 //int flags = fcntl(fd[0],F_GETFL); //flags |= O_NONBLOCK; //fcntl(fd[0],F_SETFL,flags);//设置文件描述符为非阻塞 while(1){ //--循环等待事件产生 int ready = epoll_wait(epfd,&epv,1,-1); printf("ready--------===%d\n",ready); //--读内容,输出到屏幕 char buf[6]; memset(buf,0x00,sizeof(buf)); int ret = read(epv.data.fd,buf,sizeof(buf)); //write(STDOUT_FILENO,buf,ret); printf("read:%s\n",buf); } } return 0; } 这里面用epoll 模式,在管道间通信。子进程退出循环了。但是父进程还是能够接受到事件。

Linux Epoll 接收大文件

最近在写一个文件版本管理服务器,服务器用的Linux系统,用epoll +多线程 接收大文件时发现,文件会被分成好几个小包发送和接收。 请问大佬们 在服务器端应该怎样把文件融合在一起。

使用epoll出现问题,偶然性,有时候有问题,有时候又是正常的。

我用一个线程监听,如果有数据可读,就通知另一个线程去读。下面是监听线程的代码。出现的问题就是三次握手后,服务端就自动发送了一个FIN报文,接着客户端发送数据就会收到RST void ListenThread::run() { int max_epoll=pconf->value("max_connect","1024").toInt(); short listen_port=pconf->value("listen_port","9000").toShort(); int res; struct sockaddr_in server_addr; server_addr.sin_family=AF_INET; server_addr.sin_port=htons(listen_port); server_addr.sin_addr.s_addr=htonl(INADDR_ANY); int listen_socket=socket(AF_INET,SOCK_STREAM,0); // int opts=fcntl(listen_socket,F_GETFL); // fcntl(listen_socket,F_SETFL,opts|O_NONBLOCK); res=::bind(listen_socket,(sockaddr *)&server_addr,sizeof(server_addr)); if(res!=0){ emit listen_error(); return; } res=::listen(listen_socket,max_epoll); if(res!=0){ emit listen_error(); return; } emit listen_success(); struct epoll_event ev,events[64]; int epfd=epoll_create(max_epoll); EpollEventData *eed=new EpollEventData; eed->fd=listen_socket; ev.data.ptr=eed; ev.events=EPOLLIN; epoll_ctl(epfd,EPOLL_CTL_ADD,listen_socket,&ev); while(isRun){ //qDebug()<<"listen......"; int res=epoll_wait(epfd,events,64,100); if(res<0){ emit listen_error(); } for(int i=0;i<res;i++){ if(((EpollEventData *)events[i].data.ptr)->fd==listen_socket){//有新的连接请求 //qDebug()<<"new connection in"; sockaddr_in con_addr; socklen_t addr_len; int con_socket=::accept(listen_socket,(sockaddr *)&con_addr,&addr_len); int opts=fcntl(con_socket,F_GETFL); fcntl(con_socket,F_SETFL,opts|O_NONBLOCK); EpollEventData * eed_con=new EpollEventData; struct epoll_event ev_con; eed_con->fd=con_socket; inet_ntop(AF_INET,&con_addr.sin_addr,eed_con->ip,INET_ADDRSTRLEN); ev_con.data.ptr=eed_con; ev_con.events=EPOLLIN|EPOLLONESHOT|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_ADD,con_socket,&ev_con); //qDebug()<<"new connection add"; } else if(events[i].events & EPOLLIN){//有socket数据可读 //qDebug()<<"can read"; EpollEventData *ed=(EpollEventData *)events[i].data.ptr; pthread_mutex_lock(&mutex_socket); pSocketList->push_back(ed); pthread_cond_signal(&cond_socket); pthread_mutex_unlock(&mutex_socket); //epoll_ctl(epfd,EPOLL_CTL_DEL,ed->fd,&events[i]); } else{//差错处理 } } } delete eed; ::close(listen_socket); ::close(epfd); } ![图片说明](https://img-ask.csdn.net/upload/201509/22/1442929182_831705.png)

java nio的select和linux的epoll有什么区别?

#### 最近在看关于epoll和select相关问题,但是并没有发现java的select和linux的epoll有什么区别 #### java的nio select代码如下 ``` import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; public class NioServer { private static Map<String, SocketChannel> clientMap = new HashMap<>(); public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(8899)); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { try { /** * 程序会卡在select()函数,当客户端有动作了,比如连接上了,或者是发送消息过来了,服务端才会继续走 * 当第一个客户端连接上并且是selectionKey.isAcceptable(),代码就又重新卡到了select()函数上 * 等待客户端的再次操作(无论是哪个客户端) */ selector.select(); /** * selector.selectedKeys()这段代码可以从中知道是哪个客户端,执行了什么操作 * */ Set<SelectionKey> selectionKeys = selector.selectedKeys(); selectionKeys.forEach((selectionKey) -> { final SocketChannel client; try { if (selectionKey.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel(); /** * 这代代码获取了真正的客户端socket句柄 */ client = server.accept(); client.configureBlocking(false); /** * 这句话如果不写,就相当于没有注册当消息可读时的回调函数,当客户端发送消息过来的时候 * 服务端的selector.selectedKeys()就永远不会受到这类消息 */ client.register(selector, SelectionKey.OP_READ); String key = "[" + UUID.randomUUID().toString() + "]"; clientMap.put(key, client); } else if (selectionKey.isReadable()) { client = (SocketChannel) selectionKey.channel(); ByteBuffer readBuffer = ByteBuffer.allocate(1024); int count = client.read(readBuffer); if (count > 0) { readBuffer.flip(); Charset charset = Charset.forName("utf-8"); String recvMsg = String.valueOf(charset.decode(readBuffer).array()); System.out.println(client + ":" + recvMsg); String sendKey = null; for (Map.Entry<String, SocketChannel> stringSocketChannelEntry : clientMap.entrySet()) { if (stringSocketChannelEntry.getValue() == client) { sendKey = stringSocketChannelEntry.getKey(); break; } } for (Map.Entry<String, SocketChannel> stringSocketChannelEntry : clientMap.entrySet()) { SocketChannel socketChannel = stringSocketChannelEntry.getValue(); ByteBuffer writeBuffer = ByteBuffer.allocate(1024); writeBuffer.put((sendKey + ": " + recvMsg).getBytes()); writeBuffer.flip(); socketChannel.write(writeBuffer); } } } } catch (Exception ex) { ex.printStackTrace(); } }); selectionKeys.clear(); } catch (Exception e) { e.printStackTrace(); } } } } ``` #### linux的epoll的c代码如下 ``` #include <iostream> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <cstring> using namespace std; #define MAXLINE 5 #define OPEN_MAX 100 #define LISTENQ 20 #define SERV_PORT 5000 #define INFTIM 1000 void setnonblocking(int sock) { int opts; opts=fcntl(sock,F_GETFL); if(opts<0) { perror("fcntl(sock,GETFL)"); exit(1); } opts = opts|O_NONBLOCK; if(fcntl(sock,F_SETFL,opts)<0) { perror("fcntl(sock,SETFL,opts)"); exit(1); } } int main(int argc, char* argv[]) { int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber; ssize_t n; char line[MAXLINE]; socklen_t clilen; if ( 2 == argc ) { if( (portnumber = atoi(argv[1])) < 0 ) { fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]); return 1; } } else { fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]); return 1; } //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 struct epoll_event ev,events[20]; //生成用于处理accept的epoll专用的文件描述符 //创建一个epoll文件描述符 epfd=epoll_create(256); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket设置为非阻塞方式 //setnonblocking(listenfd); //设置与要处理的事件相关的文件描述符 ev.data.fd=listenfd; //设置要处理的事件类型 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册epoll事件,将socket文件描述符listenfd的ev事件注册到epoll上 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); memset(&serveraddr, sizeof(serveraddr) ,0); serveraddr.sin_family = AF_INET; char *local_addr="127.0.0.1"; inet_aton(local_addr,&(serveraddr.sin_addr));//htons(portnumber); serveraddr.sin_port=htons(portnumber); //先bind再监听 bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr)); listen(listenfd, LISTENQ); maxi = 0; for ( ; ; ) { //等待epoll事件的发生 //param epfd表示将监听epfd的事件 //param events表示容器,一旦有事件发生,events数组会被填充 nfds=epoll_wait(epfd,events,20,500); //处理所发生的所有事件 for(i=0;i<nfds;++i) { if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。 { connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); if(connfd<0){ perror("connfd<0"); exit(1); } //setnonblocking(connfd); char *str = inet_ntoa(clientaddr.sin_addr); cout << "accapt a connection from " << str << endl; //设置用于读操作的文件描述符 ev.data.fd=connfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。 { cout << "EPOLLIN" << endl; if ( (sockfd = events[i].data.fd) < 0) continue; if ( (n = read(sockfd, line, MAXLINE)) < 0) { if (errno == ECONNRESET) { close(sockfd); events[i].data.fd = -1; } else std::cout<<"readline error"<<std::endl; } else if (n == 0) { close(sockfd); events[i].data.fd = -1; } line[n] = '/0'; cout << "read " << line << endl; //设置用于写操作的文件描述符 ev.data.fd=sockfd; //设置用于注测的写操作事件 ev.events=EPOLLOUT|EPOLLET; //修改sockfd上要处理的事件为EPOLLOUT //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events[i].events&EPOLLOUT) // 如果有数据发送 { sockfd = events[i].data.fd; write(sockfd, line, n); //设置用于读操作的文件描述符 ev.data.fd=sockfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //修改sockfd上要处理的事件为EPOLIN epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } } } return 0; } ``` #### 从上面两段代码看好像基本思想都是一样的,并没有传说中的select不知道发生的事件,只能通过循环去判断的情况。 #### 但是后来我又在网上找了一段linux的select实现的网络io代码 ``` #include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<unistd.h> #include<stdlib.h> #include<errno.h> #include<arpa/inet.h> #include<netinet/in.h> #include<string.h> #include<signal.h> #define MAXLINE 1024 #define LISTENLEN 10 #define SERV_PORT 6666 int main(int argc, char **argv) { int i, maxi, maxfd, listenfd, connfd, sockfd; int nready, client[FD_SETSIZE]; ssize_t n; fd_set rset, allset; char buf[MAXLINE]; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)); listen(listenfd, LISTENLEN); maxfd = listenfd; /* initialize */ maxi = -1; /* index into client[] array */ for (i = 0; i < FD_SETSIZE; i++) client[i] = -1; /* -1 indicates available entry */ FD_ZERO(&allset); FD_SET(listenfd, &allset); for ( ; ; ) { rset = allset; /* structure assignment */ nready = select(maxfd+1, &rset, NULL, NULL, NULL); if (FD_ISSET(listenfd, &rset)) /* new client connection */ { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &clilen); #ifdef NOTDEF printf("new client: %s, port %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL), ntohs(cliaddr.sin_port)); #endif for (i = 0; i < FD_SETSIZE; i++) if (client[i] < 0) { client[i] = connfd; /* save descriptor */ break; } if (i == FD_SETSIZE) { printf("too many clients"); exit(0); } FD_SET(connfd, &allset); /* add new descriptor to set */ if (connfd > maxfd) maxfd = connfd; /* for select */ if (i > maxi) maxi = i; /* max index in client[] array */ if (--nready <= 0) continue; /* no more readable descriptors */ } for (i = 0; i <= maxi; i++) /* check all clients for data */ { if ( (sockfd = client[i]) < 0) continue; if (FD_ISSET(sockfd, &rset)) { if ( (n = read(sockfd, buf, MAXLINE)) == 0)/* connection closed by client */ { close(sockfd); FD_CLR(sockfd, &allset); client[i] = -1; } else write(sockfd, buf, n); if (--nready <= 0) break; /* no more readable descriptors */ } } } } ``` #### 从这段代码里面确实是可以看出是通过循环判断的,我的问题是java的select是不是就是linux的epoll的思想?

epoll写聊天程序 如何实现非阻塞通信

比如 if(events[i].events&EPOLLOUT) { sockfd=events[i].data.fd; int write_bytes=write(sockfd,write_buf,10); modfd(epollfd,sockfd,EPOLLIN); } 当发送之后就修改了sockfd的状态 如果接着写信息 只有等下次另一端发送信息后 修改sockfd为EPOLLOUT才会触发 才可以看到上次对方写的消息 请问这里该怎么写才能使得两端实时接收到对方发送的消息而不用自己必须先发送消息才能看得到 还是说必须写成多线程的方式 用两个线程分别处理读和写操作?

Linux 环境下 无法加载 libnetty-transport-native-epoll.so

![图片说明](https://img-ask.csdn.net/upload/201905/29/1559095705_825533.png) ``` pom.xml 依赖如下 <dependency> <groupId>io.netty</groupId> <artifactId>netty-transport-native-epoll</artifactId> <version>4.1.23.Final</version> <classifier>linux-x86_64</classifier> </dependency> Epoll.ensureAvailability(); EventLoopGroup group = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup(); b.group(group) .channel(Epoll.isAvailable() ? EpollDatagramChannel.class : NioDatagramChannel.class) .option(ChannelOption.SO_BROADCAST, true) .option(ChannelOption.SO_RCVBUF, 1024 * 1024) .handler(new ChannelInitializer<NioDatagramChannel>() { @Override public void initChannel(final NioDatagramChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(serverHandler); } }); // linux平台下支持SO_REUSEPORT特性以提高性能 LOGGER.info("Epoll.isAvailable():"+Epoll.isAvailable()); LOGGER.info("Epoll.unavailabilityCause():"+Epoll.unavailabilityCause()); if (Epoll.isAvailable()) { b.option(EpollChannelOption.SO_REUSEPORT, true); } if (Epoll.isAvailable()) { // linux系统下使用SO_REUSEPORT特性,使得多个线程绑定同一个端口 int cpuNum = Runtime.getRuntime().availableProcessors(); LOGGER.info("using epoll reuseport and cpu:" + cpuNum); for (int i = 0; i < cpuNum; i++) { ChannelFuture future = b.bind(port).await(); if (!future.isSuccess()) { throw new Exception("bootstrap bind fail port is " + port); } } } ```

epoll异步服务端程序,客户端采用多线程访问,服务端总是返回errno 9和107

#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <pthread.h> #include <sys/stat.h> #include <sys/epoll.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/resource.h> #include <iostream> using namespace std; #define MAX_EVENTS 65535 #define SERVER_PORT 8887 #define LISTEN_BACKLOG 2048 char send_buf[64] = {0}; int setnonblocking(int& sockfd) { if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { return -1; } return 0; } void* recv_send_data(void *data) { int _socket = *(int *)data; char recvBuf[16] = {0}; int recv_len = -1; int res = 1; while(res) { recv_len = recv(_socket, recvBuf, 13, 0); if(recv_len < 0) { if(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { continue; } else { cout << "recv error! errno: " << errno << endl; break; } } else if(recv_len == 0) //对端已正常关闭 { res = 0; } if(recv_len == sizeof(recvBuf)) { res = 1; } else { res = 0; } } if(recv_len > 0) { send(_socket, send_buf, strlen(send_buf), 0); } close(_socket); } int main() { signal(SIGPIPE,SIG_IGN); sprintf(send_buf, "%s", "Hello world!"); struct rlimit rt; rt.rlim_max = rt.rlim_cur = 1048576; int epollFd = epoll_create(MAX_EVENTS); setrlimit(RLIMIT_NOFILE, &rt); /*******创建服务端socket,绑定、监听*******/ struct sockaddr_in server_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); int server_socket = socket(AF_INET, SOCK_STREAM, 0); if(server_socket < 0) { cout << "create server socket failed!" << endl; return -1; } setnonblocking(server_socket); int opt = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if(bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr))) { cout << "server bind failed!" << endl; return -1; } if(listen(server_socket, LISTEN_BACKLOG)) { cout << "server listen failed" << endl; return -1; } /**************向epollFd添加fd监听事件**************/ struct epoll_event server_ev; server_ev.events = EPOLLIN | EPOLLET; server_ev.data.fd = server_socket; if(-1 == epoll_ctl(epollFd, EPOLL_CTL_ADD, server_socket, &server_ev)) { cout << "epoll_ctl server socket failed" << endl; return -1; } while(true) { struct epoll_event events[MAX_EVENTS]; int nfds = epoll_wait(epollFd, events, MAX_EVENTS, -1); if(nfds < 0) { cout << "epoll_wait failed" << endl; return -1; } for(int i = 0; i < nfds; ++i) { if(events[i].data.fd == server_socket) { struct sockaddr_in clientAddr; socklen_t length = sizeof(clientAddr); int remote_socket = accept(events[i].data.fd, (struct sockaddr*)&clientAddr, &length); if(remote_socket < 0) { cout << "accept socket failed!" << endl; continue; } cout << "socket connect successfully" << endl; setnonblocking(remote_socket); struct epoll_event client_ev; client_ev.data.fd = remote_socket; client_ev.events = EPOLLIN | EPOLLET; if(-1 == epoll_ctl(epollFd, EPOLL_CTL_ADD, remote_socket, &client_ev)) { cout << "epoll_ctl client socket failed" << endl; return -1; } } else { pthread_t thread; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(pthread_create(&thread, &attr, recv_send_data, (void*)&(events[i].data.fd))) { cout << "create thread failed" << endl; return -1; } } } } close(server_socket); cout << "abort" << endl; return 0; }

单线程epoll的瓶颈在哪里,如何进一步提升?

普通单机下单线程epoll做的简单回射服务器的并发量为什么最高才15000/s,瓶颈在哪里,如何优化? 我本机的电脑配置大致为:联想y460,i5处理器,8G内存,普通网卡。

nginx或一些其他软件是如何使用同步的EPOLL实现异步非阻塞的?

epoll印象中是同步的io, 那么nginx或一些其他软件是如何使用同步的EPOLL实现异步非阻塞的?

使用epoll时出现的问题,出现了很奇怪的RST报文

![图片说明](https://img-ask.csdn.net/upload/201509/24/1443061385_153760.png)

Python可以这样学(第一季:Python内功修炼)

董付国系列教材《Python程序设计基础》、《Python程序设计(第2版)》、《Python可以这样学》配套视频,讲解Python 3.5.x和3.6.x语法、内置对象用法、选择与循环以及函数设计与使用、lambda表达式用法、字符串与正则表达式应用、面向对象编程、文本文件与二进制文件操作、目录操作与系统运维、异常处理结构。

获取Linux下Ftp目录树并逐步绑定到treeview

在linux下抓取目录树,双击后获取该节点子节点(逐步生成)。另外有两个类,一个是windows下的(一次性获取目录树),一个是linux下的(足部获取目录树)

NS网络模拟和协议仿真源代码

NS网络模拟和协议仿真源代码,包含代码说明及协议分析

简单的NS3网络模拟仿真(计算机网络作业)

简单的NS3网络模拟仿真,内附有PPT演示。论文评述。以及简单的安装教程。

手把手实现Java图书管理系统(附源码)

【超实用课程内容】 本课程演示的是一套基于Java的SSM框架实现的图书管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的java人群。详细介绍了图书管理系统的实现,包括:环境搭建、系统业务、技术实现、项目运行、功能演示、系统扩展等,以通俗易懂的方式,手把手的带你从零开始运行本套图书管理系统,该项目附带全部源码可作为毕设使用。 【课程如何观看?】 PC端:https://edu.csdn.net/course/detail/27513 移动端:CSDN 学院APP(注意不是CSDN APP哦) 本课程为录播课,课程2年有效观看时长,大家可以抓紧时间学习后一起讨论哦~ 【学员专享增值服务】 源码开放 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化

三个项目玩转深度学习(附1G源码)

从事大数据与人工智能开发与实践约十年,钱老师亲自见证了大数据行业的发展与人工智能的从冷到热。事实证明,计算机技术的发展,算力突破,海量数据,机器人技术等,开启了第四次工业革命的序章。深度学习图像分类一直是人工智能的经典任务,是智慧零售、安防、无人驾驶等机器视觉应用领域的核心技术之一,掌握图像分类技术是机器视觉学习的重中之重。针对现有线上学习的特点与实际需求,我们开发了人工智能案例实战系列课程。打造:以项目案例实践为驱动的课程学习方式,覆盖了智能零售,智慧交通等常见领域,通过基础学习、项目案例实践、社群答疑,三维立体的方式,打造最好的学习效果。

150讲轻松搞定Python网络爬虫

【为什么学爬虫?】 &nbsp; &nbsp; &nbsp; &nbsp;1、爬虫入手容易,但是深入较难,如何写出高效率的爬虫,如何写出灵活性高可扩展的爬虫都是一项技术活。另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要的数据,这门课程,你都能学到! &nbsp; &nbsp; &nbsp; &nbsp;2、如果是作为一个其他行业的开发者,比如app开发,web开发,学习爬虫能让你加强对技术的认知,能够开发出更加安全的软件和网站 【课程设计】 一个完整的爬虫程序,无论大小,总体来说可以分成三个步骤,分别是: 网络请求:模拟浏览器的行为从网上抓取数据。 数据解析:将请求下来的数据进行过滤,提取我们想要的数据。 数据存储:将提取到的数据存储到硬盘或者内存中。比如用mysql数据库或者redis等。 那么本课程也是按照这几个步骤循序渐进的进行讲解,带领学生完整的掌握每个步骤的技术。另外,因为爬虫的多样性,在爬取的过程中可能会发生被反爬、效率低下等。因此我们又增加了两个章节用来提高爬虫程序的灵活性,分别是: 爬虫进阶:包括IP代理,多线程爬虫,图形验证码识别、JS加密解密、动态网页爬虫、字体反爬识别等。 Scrapy和分布式爬虫:Scrapy框架、Scrapy-redis组件、分布式爬虫等。 通过爬虫进阶的知识点我们能应付大量的反爬网站,而Scrapy框架作为一个专业的爬虫框架,使用他可以快速提高我们编写爬虫程序的效率和速度。另外如果一台机器不能满足你的需求,我们可以用分布式爬虫让多台机器帮助你快速爬取数据。 &nbsp; 从基础爬虫到商业化应用爬虫,本套课程满足您的所有需求! 【课程服务】 专属付费社群+每周三讨论会+1v1答疑

cuda开发cutilDLL

包括cutil32.dll、cutil32D.dll、cutil32.lib、cutil32D.lib,以及附带的glew32.lib/freeglut.lib

深度学习原理+项目实战+算法详解+主流框架(套餐)

深度学习系列课程从深度学习基础知识点开始讲解一步步进入神经网络的世界再到卷积和递归神经网络,详解各大经典网络架构。实战部分选择当下最火爆深度学习框架PyTorch与Tensorflow/Keras,全程实战演示框架核心使用与建模方法。项目实战部分选择计算机视觉与自然语言处理领域经典项目,从零开始详解算法原理,debug模式逐行代码解读。适合准备就业和转行的同学们加入学习! 建议按照下列课程顺序来进行学习 (1)掌握深度学习必备经典网络架构 (2)深度框架实战方法 (3)计算机视觉与自然语言处理项目实战。(按照课程排列顺序即可)

Tensorflow与python3.7适配版本

tensorflow与python3.7匹配的最新库,更新了python3.7以后可以自行下载,或者去国外python的扩展包下载界面自行下载。

4小时玩转微信小程序——基础入门与微信支付实战

这是一个门针对零基础学员学习微信小程序开发的视频教学课程。课程采用腾讯官方文档作为教程的唯一技术资料来源。杜绝网络上质量良莠不齐的资料给学员学习带来的障碍。 视频课程按照开发工具的下载、安装、使用、程序结构、视图层、逻辑层、微信小程序等几个部分组织课程,详细讲解整个小程序的开发过程

专为程序员设计的数学课

<p> 限时福利限时福利,<span>15000+程序员的选择!</span> </p> <p> 购课后添加学习助手(微信号:csdn590),按提示消息领取编程大礼包!并获取讲师答疑服务! </p> <p> <br> </p> <p> 套餐中一共包含5门程序员必学的数学课程(共47讲) </p> <p> 课程1:《零基础入门微积分》 </p> <p> 课程2:《数理统计与概率论》 </p> <p> 课程3:《代码学习线性代数》 </p> <p> 课程4:《数据处理的最优化》 </p> <p> 课程5:《马尔可夫随机过程》 </p> <p> <br> </p> <p> 哪些人适合学习这门课程? </p> <p> 1)大学生,平时只学习了数学理论,并未接触如何应用数学解决编程问题; </p> <p> 2)对算法、数据结构掌握程度薄弱的人,数学可以让你更好的理解算法、数据结构原理及应用; </p> <p> 3)看不懂大牛代码设计思想的人,因为所有的程序设计底层逻辑都是数学; </p> <p> 4)想学习新技术,如:人工智能、机器学习、深度学习等,这门课程是你的必修课程; </p> <p> 5)想修炼更好的编程内功,在遇到问题时可以灵活的应用数学思维解决问题。 </p> <p> <br> </p> <p> 在这门「专为程序员设计的数学课」系列课中,我们保证你能收获到这些:<br> <br> <span> </span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">①价值300元编程课程大礼包</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">②应用数学优化代码的实操方法</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">③数学理论在编程实战中的应用</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">④程序员必学的5大数学知识</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">⑤人工智能领域必修数学课</span> </p> <p> <br> 备注:此课程只讲程序员所需要的数学,即使你数学基础薄弱,也能听懂,只需要初中的数学知识就足矣。<br> <br> 如何听课? </p> <p> 1、登录CSDN学院 APP 在我的课程中进行学习; </p> <p> 2、登录CSDN学院官网。 </p> <p> <br> </p> <p> 购课后如何领取免费赠送的编程大礼包和加入答疑群? </p> <p> 购课后,添加助教微信:<span> csdn590</span>,按提示领取编程大礼包,或观看付费视频的第一节内容扫码进群答疑交流! </p> <p> <img src="https://img-bss.csdn.net/201912251155398753.jpg" alt=""> </p>

实现简单的文件系统

实验内容: 通过对具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部功能和实现过程的理解。 要求: 1.在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简

机器学习初学者必会的案例精讲

通过六个实际的编码项目,带领同学入门人工智能。这些项目涉及机器学习(回归,分类,聚类),深度学习(神经网络),底层数学算法,Weka数据挖掘,利用Git开源项目实战等。

四分之一悬架模型simulink.7z

首先建立了四分之一车辆悬架系统的数学模型,应用MATLAB/Simulink软件建立该系统的仿真模型,并输入路面激励为随机激励,控制不同的悬架刚度和阻尼,选用最优的参数得到车辆悬架的振动加速度变化曲线

MFC一站式终极全套课程包

该套餐共包含从C小白到C++到MFC的全部课程,整套学下来绝对成为一名C++大牛!!!

C++语言基础视频教程

C++语言基础视频培训课程:本课与主讲者在大学开出的程序设计课程直接对接,准确把握知识点,注重教学视频与实践体系的结合,帮助初学者有效学习。本教程详细介绍C++语言中的封装、数据隐藏、继承、多态的实现等入门知识;主要包括类的声明、对象定义、构造函数和析构函数、运算符重载、继承和派生、多态性实现等。 课程需要有C语言程序设计的基础(可以利用本人开出的《C语言与程序设计》系列课学习)。学习者能够通过实践的方式,学会利用C++语言解决问题,具备进一步学习利用C++开发应用程序的基础。

Java8零基础入门视频教程

这门课程基于主流的java8平台,由浅入深的详细讲解了java SE的开发技术,可以使java方向的入门学员,快速扎实的掌握java开发技术!

HoloLens2开发入门教程

本课程为HoloLens2开发入门教程,讲解部署开发环境,安装VS2019,Unity版本,Windows SDK,创建Unity项目,讲解如何使用MRTK,编辑器模拟手势交互,打包VS工程并编译部署应用到HoloLens上等。

C/C++学习指南全套教程

C/C++学习的全套教程,从基本语法,基本原理,到界面开发、网络开发、Linux开发、安全算法,应用尽用。由毕业于清华大学的业内人士执课,为C/C++编程爱好者的教程。

pokemmo的资源

pokemmo必须的4个rom 分别为绿宝石 火红 心金 黑白 还有汉化补丁 资源不错哦 记得下载

test_head.py

本文件主要是针对使用dlib的imglab标注工具标记的目标检测框和关键点检测而生成的xml文件, 转换为coco数据集格式.

Java面试史上最全的JAVA专业术语面试100问 (前1-50)

前言: 说在前面, 面试题是根据一些朋友去面试提供的,再就是从网上整理了一些。 先更新50道,下一波吧后面的也更出来。 求赞求关注!! 废话也不多说,现在就来看看有哪些面试题 1、面向对象的特点有哪些? 抽象、继承、封装、多态。 2、接口和抽象类有什么联系和区别? 3、重载和重写有什么区别? 4、java有哪些基本数据类型? 5、数组有没有length()方法?String有没有length()方法? 数组没有length()方法,它有length属性。 String有length()方法。 集合求长度用

2019 AI开发者大会

2019 AI开发者大会(AI ProCon 2019)是由中国IT社区CSDN主办的AI技术与产业年度盛会。多年经验淬炼,如今蓄势待发:2019年9月6-7日,大会将有近百位中美顶尖AI专家、知名企业代表以及千余名AI开发者齐聚北京,进行技术解读和产业论证。我们不空谈口号,只谈技术,诚挚邀请AI业内人士一起共铸人工智能新篇章!

linux“开发工具三剑客”速成攻略

工欲善其事,必先利其器。Vim+Git+Makefile是Linux环境下嵌入式开发常用的工具。本专题主要面向初次接触Linux的新手,熟练掌握工作中常用的工具,在以后的学习和工作中提高效率。

DirectX修复工具V4.0增强版

DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复

20行代码教你用python给证件照换底色

20行代码教你用python给证件照换底色

2019 Python开发者日-培训

本次活动将秉承“只讲技术,拒绝空谈”的理念,邀请十余位身处一线的Python技术专家,重点围绕Web开发、自动化运维、数据分析、人工智能等技术模块,分享真实生产环境中使用Python应对IT挑战的真知灼见。此外,针对不同层次的开发者,大会还安排了深度培训实操环节,为开发者们带来更多深度实战的机会。

我以为我对Mysql事务很熟,直到我遇到了阿里面试官

太惨了,面试又被吊打

相关热词 c#框体中的退出函数 c# 按钮透明背景 c# idl 混编出错 c#在位置0处没有任何行 c# 循环给数组插入数据 c# 多线程死锁的例子 c# 钉钉读取员工排班 c# label 不显示 c#裁剪影像 c#工作进程更新ui
立即提问