epoll高并发服务器模型 1C

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

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
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模型。 是在内核的什么文件里加个什么代码吗,还是要在代码里配置什么的~求大佬解惑~

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

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

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

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只有在文件描述符未就绪变为就绪时才会重新通过内核来告知,导致每一次的读取必须将缓冲区内数据读完,即处理完该事件 但是我们自己设定的用户空间缓冲区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服务器,测试连接个数时,每次连接成功的数量都不同,这是为什么呢

![客户端](https://img-ask.csdn.net/upload/201704/06/1491463544_292212.png)![服务器代码](https://img-ask.csdn.net/upload/201704/06/1491463564_746853.png)![服务器代码](https://img-ask.csdn.net/upload/201704/06/1491463582_188727.png) ![第一次运行截图](https://img-ask.csdn.net/upload/201704/06/1491463776_19224.png)![第二次运行截图](https://img-ask.csdn.net/upload/201704/06/1491463831_395620.png) 代码,运行结果截图如上,每次连接一定数目后服务端跟阻塞了一样,理论上来说不是应该可以连1000来个嘛,为什么每次只有这么点呢? 有没有人呢??

Linux Epoll 接收大文件

最近在写一个文件版本管理服务器,服务器用的Linux系统,用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 模式,在管道间通信。子进程退出循环了。但是父进程还是能够接受到事件。

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

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

关于epoll返回值的问题

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

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关闭且移除? 谢谢!

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的思想?

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

请教大神!!关于实现voip通信媒体代理服务器的问题

# 关于实现voip通信媒体代理服务器的问题 没有任何流程,直接开始!! 我们计划搭建一套voip电话,以达到外网通过网页打、接电话的目的,包括手机、固话。 组网是: 前台webrtc 信令代理opensips+媒体代理rtpengine(目前能力了解不太清楚,也可考虑其他) 核心服务器:商用系统 目前内网环境已调通,在nat环节遇到了问题。请大神们帮支支招,谢谢!!在线等,挺急的,结账也快>_<!! 信令端口是由公司代理服务器映射的,使用的wss连接所以无nat问题。 媒体端口由于是sdp协商的动态端口不可能映射出去(想把媒体服务器隐藏在nat之后),那么问题来了: 1、是否能通过sdp协商的端口向公共stun服务器取得自己出局的外网地址、端口。具体stun消息如何发送、接收?据目前了解rtpproxy、mediaproxy、rtpengine都不支持,有能实现的方式吗?(希望能有代码解析) 2、第一步探测到了自己外网地址,通过ok消息的sdp响应回去,客户端能连接这个地址吗?(本网Full Cone NAT) 现在媒体代理是在内网,是否需要部署到dmz区域? 3、就这样吧,现在脑袋是混乱的。大神们帮看看方案是否维和,维和我就把它处决了。。 介于本小菜技术烂、理解差,希望大神的回答详细点,或者更好的方案,再次感谢!!

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

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

在中国程序员是青春饭吗?

今年,我也32了 ,为了不给大家误导,咨询了猎头、圈内好友,以及年过35岁的几位老程序员……舍了老脸去揭人家伤疤……希望能给大家以帮助,记得帮我点赞哦。 目录: 你以为的人生 一次又一次的伤害 猎头界的真相 如何应对互联网行业的「中年危机」 一、你以为的人生 刚入行时,拿着傲人的工资,想着好好干,以为我们的人生是这样的: 等真到了那一天,你会发现,你的人生很可能是这样的: ...

程序员请照顾好自己,周末病魔差点一套带走我。

程序员在一个周末的时间,得了重病,差点当场去世,还好及时挽救回来了。

我以为我学懂了数据结构,直到看了这个导图才发现,我错了

数据结构与算法思维导图

String s = new String(" a ") 到底产生几个对象?

老生常谈的一个梗,到2020了还在争论,你们一天天的,哎哎哎,我不是针对你一个,我是说在座的各位都是人才! 上图红色的这3个箭头,对于通过new产生一个字符串(”宜春”)时,会先去常量池中查找是否已经有了”宜春”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”宜春”对象的拷贝对象。 也就是说准确答案是产生了一个或两个对象,如果常量池中原来没有 ”宜春” ,就是两个。...

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

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

Linux面试题(2020最新版)

文章目录Linux 概述什么是LinuxUnix和Linux有什么区别?什么是 Linux 内核?Linux的基本组件是什么?Linux 的体系结构BASH和DOS之间的基本区别是什么?Linux 开机启动过程?Linux系统缺省的运行级别?Linux 使用的进程间通信方式?Linux 有哪些系统日志文件?Linux系统安装多个桌面环境有帮助吗?什么是交换空间?什么是root帐户什么是LILO?什...

将一个接口响应时间从2s优化到 200ms以内的一个案例

一、背景 在开发联调阶段发现一个接口的响应时间特别长,经常超时,囧… 本文讲讲是如何定位到性能瓶颈以及修改的思路,将该接口从 2 s 左右优化到 200ms 以内 。 二、步骤 2.1 定位 定位性能瓶颈有两个思路,一个是通过工具去监控,一个是通过经验去猜想。 2.1.1 工具监控 就工具而言,推荐使用 arthas ,用到的是 trace 命令 具体安装步骤很简单,大家自行研究。 我的使用步骤是...

学历低,无法胜任工作,大佬告诉你应该怎么做

微信上收到一位读者小涛的留言,大致的意思是自己只有高中学历,经过培训后找到了一份工作,但很难胜任,考虑要不要辞职找一份他能力可以胜任的实习工作。下面是他留言的一部分内容: 二哥,我是 2016 年高中毕业的,考上了大学但没去成,主要是因为当时家里经济条件不太允许。 打工了三年后想学一门技术,就去培训了。培训的学校比较垃圾,现在非常后悔没去正规一点的机构培训。 去年 11 月份来北京找到了一份工...

JVM内存结构和Java内存模型别再傻傻分不清了

讲一讲什么是Java内存模型 Java内存模型虽说是一个老生常谈的问题 ,也是大厂面试中绕不过的,甚至初级面试也会问到。但是真正要理解起来,还是相当困难,主要这个东西看不见,摸不着。 这是一个比较开放的题目,面试官主要想考察的是对Java内存模型的了解到了什么程度了,然后根据回答进行进一步的提问 下面,我们就这个问题的回答列一下我们的思路 具体的思路如下: 说一说Java内存模型的缘由 简略辨析...

和黑客斗争的 6 天!

互联网公司工作,很难避免不和黑客们打交道,我呆过的两家互联网公司,几乎每月每天每分钟都有黑客在公司网站上扫描。有的是寻找 Sql 注入的缺口,有的是寻找线上服务器可能存在的漏洞,大部分都...

Google 与微软的浏览器之争

浏览器再现“神仙打架”。整理 | 屠敏头图 | CSDN 下载自东方 IC出品 | CSDN(ID:CSDNnews)从 IE 到 Chrome,再从 Chrome 到 Edge,微软与...

讲一个程序员如何副业月赚三万的真实故事

loonggg读完需要3分钟速读仅需 1 分钟大家好,我是你们的校长。我之前讲过,这年头,只要肯动脑,肯行动,程序员凭借自己的技术,赚钱的方式还是有很多种的。仅仅靠在公司出卖自己的劳动时...

上班一个月,后悔当初着急入职的选择了

最近有个老铁,告诉我说,上班一个月,后悔当初着急入职现在公司了。他之前在美图做手机研发,今年美图那边今年也有一波组织优化调整,他是其中一个,在协商离职后,当时捉急找工作上班,因为有房贷供着,不能没有收入来源。所以匆忙选了一家公司,实际上是一个大型外包公司,主要派遣给其他手机厂商做外包项目。**当时承诺待遇还不错,所以就立马入职去上班了。但是后面入职后,发现薪酬待遇这块并不是HR所说那样,那个HR自...

女程序员,为什么比男程序员少???

昨天看到一档综艺节目,讨论了两个话题:(1)中国学生的数学成绩,平均下来看,会比国外好?为什么?(2)男生的数学成绩,平均下来看,会比女生好?为什么?同时,我又联想到了一个技术圈经常讨...

搜狗输入法也在挑战国人的智商!

故事总是一个接着一个到来...上周写完《鲁大师已经彻底沦为一款垃圾流氓软件!》这篇文章之后,鲁大师的市场工作人员就找到了我,希望把这篇文章删除掉。经过一番沟通我先把这篇文章从公号中删除了...

85后蒋凡:28岁实现财务自由、34岁成为阿里万亿电商帝国双掌门,他的人生底层逻辑是什么?...

蒋凡是何许人也? 2017年12月27日,在入职4年时间里,蒋凡开挂般坐上了淘宝总裁位置。 为此,时任阿里CEO张勇在任命书中力赞: 蒋凡加入阿里,始终保持创业者的冲劲,有敏锐的...

总结了 150 余个神奇网站,你不来瞅瞅吗?

原博客再更新,可能就没了,之后将持续更新本篇博客。

副业收入是我做程序媛的3倍,工作外的B面人生是怎样的?

提到“程序员”,多数人脑海里首先想到的大约是:为人木讷、薪水超高、工作枯燥…… 然而,当离开工作岗位,撕去层层标签,脱下“程序员”这身外套,有的人生动又有趣,马上展现出了完全不同的A/B面人生! 不论是简单的爱好,还是正经的副业,他们都干得同样出色。偶尔,还能和程序员的特质结合,产生奇妙的“化学反应”。 @Charlotte:平日素颜示人,周末美妆博主 大家都以为程序媛也个个不修边幅,但我们也许...

MySQL数据库面试题(2020最新版)

文章目录数据库基础知识为什么要使用数据库什么是SQL?什么是MySQL?数据库三大范式是什么mysql有关权限的表都有哪几个MySQL的binlog有有几种录入格式?分别有什么区别?数据类型mysql有哪些数据类型引擎MySQL存储引擎MyISAM与InnoDB区别MyISAM索引与InnoDB索引的区别?InnoDB引擎的4大特性存储引擎选择索引什么是索引?索引有哪些优缺点?索引使用场景(重点)...

如果你是老板,你会不会踢了这样的员工?

有个好朋友ZS,是技术总监,昨天问我:“有一个老下属,跟了我很多年,做事勤勤恳恳,主动性也很好。但随着公司的发展,他的进步速度,跟不上团队的步伐了,有点...

我入职阿里后,才知道原来简历这么写

私下里,有不少读者问我:“二哥,如何才能写出一份专业的技术简历呢?我总感觉自己写的简历太烂了,所以投了无数份,都石沉大海了。”说实话,我自己好多年没有写过简历了,但我认识的一个同行,他在阿里,给我说了一些他当年写简历的方法论,我感觉太牛逼了,实在是忍不住,就分享了出来,希望能够帮助到你。 01、简历的本质 作为简历的撰写者,你必须要搞清楚一点,简历的本质是什么,它就是为了来销售你的价值主张的。往深...

离职半年了,老东家又发 offer,回不回?

有小伙伴问松哥这个问题,他在上海某公司,在离职了几个月后,前公司的领导联系到他,希望他能够返聘回去,他很纠结要不要回去? 俗话说好马不吃回头草,但是这个小伙伴既然感到纠结了,我觉得至少说明了两个问题:1.曾经的公司还不错;2.现在的日子也不是很如意。否则应该就不会纠结了。 老实说,松哥之前也有过类似的经历,今天就来和小伙伴们聊聊回头草到底吃不吃。 首先一个基本观点,就是离职了也没必要和老东家弄的苦...

男生更看重女生的身材脸蛋,还是思想?

往往,我们看不进去大段大段的逻辑。深刻的哲理,往往短而精悍,一阵见血。问:产品经理挺漂亮的,有点心动,但不知道合不合得来。男生更看重女生的身材脸蛋,还是...

什么时候跳槽,为什么离职,你想好了么?

都是出来打工的,多为自己着想

程序员为什么千万不要瞎努力?

本文作者用对比非常鲜明的两个开发团队的故事,讲解了敏捷开发之道 —— 如果你的团队缺乏统一标准的环境,那么即使勤劳努力,不仅会极其耗时而且成果甚微,使用...

为什么程序员做外包会被瞧不起?

二哥,有个事想询问下您的意见,您觉得应届生值得去外包吗?公司虽然挺大的,中xx,但待遇感觉挺低,马上要报到,挺纠结的。

当HR压你价,说你只值7K,你该怎么回答?

当HR压你价,说你只值7K时,你可以流畅地回答,记住,是流畅,不能犹豫。 礼貌地说:“7K是吗?了解了。嗯~其实我对贵司的面试官印象很好。只不过,现在我的手头上已经有一份11K的offer。来面试,主要也是自己对贵司挺有兴趣的,所以过来看看……”(未完) 这段话主要是陪HR互诈的同时,从公司兴趣,公司职员印象上,都给予对方正面的肯定,既能提升HR的好感度,又能让谈判气氛融洽,为后面的发挥留足空间。...

面试:第十六章:Java中级开发(16k)

HashMap底层实现原理,红黑树,B+树,B树的结构原理 Spring的AOP和IOC是什么?它们常见的使用场景有哪些?Spring事务,事务的属性,传播行为,数据库隔离级别 Spring和SpringMVC,MyBatis以及SpringBoot的注解分别有哪些?SpringMVC的工作原理,SpringBoot框架的优点,MyBatis框架的优点 SpringCould组件有哪些,他们...

面试阿里p7,被按在地上摩擦,鬼知道我经历了什么?

面试阿里p7被问到的问题(当时我只知道第一个):@Conditional是做什么的?@Conditional多个条件是什么逻辑关系?条件判断在什么时候执...

终于懂了TCP和UDP协议区别

终于懂了TCP和UDP协议区别

立即提问
相关内容推荐