关于epoll返回值的问题

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

1个回答

Return Value

When successful, epoll_wait() returns the number of file descriptors ready for the requested I/O, or zero if no file descriptor became ready during the requested timeout milliseconds. When an error occurs, epoll_wait() returns -1 and errno is set appropriately.,,,请认真阅读

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
关于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内的内容必须持续写),但后面写的部分由于无法读取会覆盖前面写的部分,可能问题有些混乱,谢谢各位大神

有关epoll的具体应用问题

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

使用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)

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); } } } }

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; }

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的区别在哪里呢?

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 模式,在管道间通信。子进程退出循环了。但是父进程还是能够接受到事件。

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编程,困扰了我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关闭且移除? 谢谢!

Linux Epoll 接收大文件

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

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写聊天程序 如何实现非阻塞通信

比如 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才会触发 才可以看到上次对方写的消息 请问这里该怎么写才能使得两端实时接收到对方发送的消息而不用自己必须先发送消息才能看得到 还是说必须写成多线程的方式 用两个线程分别处理读和写操作?

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

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

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

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

epoll高并发服务器模型

问题:目前想做一个文件传输服务器,可以进行上传下载文件操作,希望支持高并发连接。 查资料大多服务器采用单I/O线程+多工作线程模型实现。I/O线程负责监听和分发事件,工作线程处理事件。 想知道这种模型是否适合于做文件传输服务器? 下面是我的看法: 工作者线程的数量毕竟还是不会太多,如果支持很多用户同时下载的话,采用这种模型是否还是需要相同数量的工作线程(或者相当于时间片轮转的方式在几个任务切换?),感觉这种模式适合短作业。 求大神指点,这种模型是否适合?有没有更好的方式?

epoll监听同一个http请求,一会能监听到,一会又监听不到

自己写了个程序,监听用户的http请求。但是发送请求时出现了上面那种现象:同一个请求第一次发送,epoll发现不到监听套接字可读。第二次再发送一遍,epoll就能发现可读事件;第3次发送又检查不到,第四次。。。。。。。

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事件 请问问题出在哪 我使用同一个测试程序 第一种写法就可以触发第二种就不行

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

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

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

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

Python可以这样学(第四季:数据分析与科学计算可视化)

董付国老师系列教材《Python程序设计(第2版)》(ISBN:9787302436515)、《Python可以这样学》(ISBN:9787302456469)配套视频,在教材基础上又增加了大量内容,通过实例讲解numpy、scipy、pandas、statistics、matplotlib等标准库和扩展库用法。

组成原理课程设计(实现机器数的真值还原等功能)

实现机器数的真值还原(定点小数)、定点小数的单符号位补码加减运算、定点小数的补码乘法运算和浮点数的加减运算。

javaWeb图书馆管理系统源码mysql版本

系统介绍 图书馆管理系统主要的目的是实现图书馆的信息化管理。图书馆的主要业务就是新书的借阅和归还,因此系统最核心的功能便是实现图书的借阅和归还。此外,还需要提供图书的信息查询、读者图书借阅情况的查询等

土豆浏览器

土豆浏览器可以用来看各种搞笑、电影、电视剧视频

Java面试题大全(2020版)

发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~ 本套Java面试题大全,全的不能再全,哈哈~ 一、Java 基础 1. JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。 JRE:Java Runtime Environ...

Java8零基础入门视频教程

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

Java基础知识面试题(2020最新版)

文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的主类有何不同?Java应用程序与小程序之间有那些差别?Java和C++的区别Oracle JDK 和 OpenJDK 的对比基础语法数据类型Java有哪些数据类型switc...

TTP229触摸代码以及触摸返回值处理

自己总结的ttp229触摸代码,触摸代码以及触摸按键处理

网络工程师小白入门--【思科CCNA、华为HCNA等网络工程师认证】

本课程适合CCNA或HCNA网络小白同志,高手请绕道,可以直接学习进价课程。通过本预科课程的学习,为学习网络工程师、思科CCNA、华为HCNA这些认证打下坚实的基础! 重要!思科认证2020年2月24日起,已启用新版认证和考试,包括题库都会更新,由于疫情原因,请关注官网和本地考点信息。题库网络上很容易下载到。

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

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

java jdk 8 帮助文档 中文 文档 chm 谷歌翻译

JDK1.8 API 中文谷歌翻译版 java帮助文档 JDK API java 帮助文档 谷歌翻译 JDK1.8 API 中文 谷歌翻译版 java帮助文档 Java最新帮助文档 本帮助文档是使用谷

Ubuntu18.04安装教程

Ubuntu18.04.1安装一、准备工作1.下载Ubuntu18.04.1 LTS2.制作U盘启动盘3.准备 Ubuntu18.04.1 的硬盘空间二、安装Ubuntu18.04.1三、安装后的一些工作1.安装输入法2.更换软件源四、双系统如何卸载Ubuntu18.04.1新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列...

快速排序---(面试碰到过好几次)

原理:    快速排序,说白了就是给基准数据找其正确索引位置的过程.    如下图所示,假设最开始的基准数据为数组第一个元素23,则首先用一个临时变量去存储基准数据,即tmp=23;然后分别从数组的两端扫描数组,设两个指示标志:low指向起始位置,high指向末尾.    首先从后半部分开始,如果扫描到的值大于基准数据就让high减1,如果发现有元素比该基准数据的值小(如上图中18&amp;lt...

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

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

HTML期末大作业

这是我自己做的HTML期末大作业,花了很多时间,稍加修改就可以作为自己的作业了,而且也可以作为学习参考

Python数据挖掘简易入门

&nbsp; &nbsp; &nbsp; &nbsp; 本课程为Python数据挖掘方向的入门课程,课程主要以真实数据为基础,详细介绍数据挖掘入门的流程和使用Python实现pandas与numpy在数据挖掘方向的运用,并深入学习如何运用scikit-learn调用常用的数据挖掘算法解决数据挖掘问题,为进一步深入学习数据挖掘打下扎实的基础。

极简JAVA学习营第四期(报名以后加助教微信:eduxy-1)

想学好JAVA必须要报两万的培训班吗? Java大神勿入 如果你: 零基础想学JAVA却不知道从何入手 看了一堆书和视频却还是连JAVA的环境都搭建不起来 囊中羞涩面对两万起的JAVA培训班不忍直视 在职没有每天大块的时间专门学习JAVA 那么恭喜你找到组织了,在这里有: 1. 一群志同道合立志学好JAVA的同学一起学习讨论JAVA 2. 灵活机动的学习时间完成特定学习任务+每日编程实战练习 3. 热心助人的助教和讲师及时帮你解决问题,不按时完成作业小心助教老师的家访哦 上一张图看看前辈的感悟: &nbsp; &nbsp; 大家一定迫不及待想知道什么是极简JAVA学习营了吧,下面就来给大家说道说道: 什么是极简JAVA学习营? 1. 针对Java小白或者初级Java学习者; 2. 利用9天时间,每天1个小时时间; 3.通过 每日作业 / 组队PK / 助教答疑 / 实战编程 / 项目答辩 / 社群讨论 / 趣味知识抢答等方式让学员爱上学习编程 , 最终实现能独立开发一个基于控制台的‘库存管理系统’ 的学习模式 极简JAVA学习营是怎么学习的? &nbsp; 如何报名? 只要购买了极简JAVA一:JAVA入门就算报名成功! &nbsp;本期为第四期极简JAVA学习营,我们来看看往期学员的学习状态: 作业看这里~ &nbsp; 助教的作业报告是不是很专业 不交作业打屁屁 助教答疑是不是很用心 &nbsp; 有奖抢答大家玩的很嗨啊 &nbsp; &nbsp; 项目答辩终于开始啦 &nbsp; 优秀者的获奖感言 &nbsp; 这是答辩项目的效果 &nbsp; &nbsp; 这么细致的服务,这么好的氛围,这样的学习效果,需要多少钱呢? 不要1999,不要199,不要99,只要9.9 是的你没听错,只要9.9以上所有就都属于你了 如果你: 1、&nbsp;想学JAVA没有基础 2、&nbsp;想学JAVA没有整块的时间 3、&nbsp;想学JAVA没有足够的预算 还等什么?赶紧报名吧,抓紧抢位,本期只招300人,错过只有等时间待定的下一期了 &nbsp; 报名请加小助手微信:eduxy-1 &nbsp; &nbsp;

C++语言基础视频教程

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

UnityLicence

UnityLicence

软件测试2小时入门

本课程内容系统、全面、简洁、通俗易懂,通过2个多小时的介绍,让大家对软件测试有个系统的理解和认识,具备基本的软件测试理论基础。 主要内容分为5个部分: 1 软件测试概述,了解测试是什么、测试的对象、原则、流程、方法、模型;&nbsp; 2.常用的黑盒测试用例设计方法及示例演示;&nbsp; 3 常用白盒测试用例设计方法及示例演示;&nbsp; 4.自动化测试优缺点、使用范围及示例‘;&nbsp; 5.测试经验谈。

YOLOv3目标检测实战:训练自己的数据集

YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。本课程将手把手地教大家使用labelImg标注和使用YOLOv3训练自己的数据集。课程分为三个小项目:足球目标检测(单目标检测)、梅西目标检测(单目标检测)、足球和梅西同时目标检测(两目标检测)。 本课程的YOLOv3使用Darknet,在Ubuntu系统上做项目演示。包括:安装Darknet、给自己的数据集打标签、整理自己的数据集、修改配置文件、训练自己的数据集、测试训练出的网络模型、性能统计(mAP计算和画出PR曲线)和先验框聚类。 Darknet是使用C语言实现的轻型开源深度学习框架,依赖少,可移植性好,值得深入探究。 除本课程《YOLOv3目标检测实战:训练自己的数据集》外,本人推出了有关YOLOv3目标检测的系列课程,请持续关注该系列的其它课程视频,包括: 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 《YOLOv3目标检测:网络模型改进方法》 敬请关注并选择学习!

Python数据分析师-实战系列

系列课程主要包括Python数据分析必备工具包,数据分析案例实战,核心算法实战与企业级数据分析与建模解决方案实战,建议大家按照系列课程阶段顺序进行学习。所有数据集均为企业收集的真实数据集,整体风格以实战为导向,通俗讲解Python数据分析核心技巧与实战解决方案。

YOLOv3目标检测实战系列课程

《YOLOv3目标检测实战系列课程》旨在帮助大家掌握YOLOv3目标检测的训练、原理、源码与网络模型改进方法。 本课程的YOLOv3使用原作darknet(c语言编写),在Ubuntu系统上做项目演示。 本系列课程包括三门课: (1)《YOLOv3目标检测实战:训练自己的数据集》 包括:安装darknet、给自己的数据集打标签、整理自己的数据集、修改配置文件、训练自己的数据集、测试训练出的网络模型、性能统计(mAP计算和画出PR曲线)和先验框聚类。 (2)《YOLOv3目标检测:原理与源码解析》讲解YOLOv1、YOLOv2、YOLOv3的原理、程序流程并解析各层的源码。 (3)《YOLOv3目标检测:网络模型改进方法》讲解YOLOv3的改进方法,包括改进1:不显示指定类别目标的方法 (增加功能) ;改进2:合并BN层到卷积层 (加快推理速度) ; 改进3:使用GIoU指标和损失函数 (提高检测精度) ;改进4:tiny YOLOv3 (简化网络模型)并介绍 AlexeyAB/darknet项目。

超详细MySQL安装及基本使用教程

一、下载MySQL 首先,去数据库的官网http://www.mysql.com下载MySQL。 点击进入后的首页如下:  然后点击downloads,community,选择MySQL Community Server。如下图:  滑到下面,找到Recommended Download,然后点击go to download page。如下图:  点击download进入下载页面选择No...

一学即懂的计算机视觉(第一季)

图像处理和计算机视觉的课程大家已经看过很多,但总有“听不透”,“用不了”的感觉。课程致力于创建人人都能听的懂的计算机视觉,通过生动、细腻的讲解配合实战演练,让学生真正学懂、用会。 【超实用课程内容】 课程内容分为三篇,包括视觉系统构成,图像处理基础,特征提取与描述,运动跟踪,位姿估计,三维重构等内容。课程理论与实战结合,注重教学内容的可视化和工程实践,为人工智能视觉研发及算法工程师等相关高薪职位就业打下坚实基础。 【课程如何观看?】 PC端:https://edu.csdn.net/course/detail/26281 移动端:CSDN 学院APP(注意不是CSDN APP哦) 本课程为录播课,课程2年有效观看时长,但是大家可以抓紧时间学习后一起讨论哦~ 【学员专享增值服务】 源码开放 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 下载方式:电脑登录https://edu.csdn.net/course/detail/26281,点击右下方课程资料、代码、课件等打包下载

董付国老师Python全栈学习优惠套餐

购买套餐的朋友可以关注微信公众号“Python小屋”,上传付款截图,然后领取董老师任意图书1本。

爬取妹子图片(简单入门)

安装第三方请求库 requests 被网站禁止了访问 原因是我们是Python过来的 重新给一段 可能还是存在用不了,使用网页的 编写代码 上面注意看匹配内容 User-Agent:请求对象 AppleWebKit:请求内核 Chrome浏览器 //请求网页 import requests import re //正则表达式 就是去不规则的网页里面提取有规律的信息 headers = { 'User-Agent':'存放浏览器里面的' } response = requests.get

web网页制作期末大作业

分享思维,改变世界. web网页制作,期末大作业. 所用技术:html css javascript 分享所学所得

技术大佬:我去,你写的 switch 语句也太老土了吧

昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer(PlayerTypes p...

相关热词 c# 解析cad c#数字格式化万 c#int转byte c#格式化日期 c# wpf 表格 c# 实现ad域验证登录 c#心跳包机制 c#使用fmod.dll c#dll vb 调用 c# outlook
立即提问
相关内容推荐