user-0 提问: linux+epoll丢失连接问题

回复:
user: user-1
content: http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程

user: user-0
content: @赵4老师  解决了，是由于我客户端为了简便没有写日志，直接重定向导致的，我重写了客户端服务端，都打上了日志，抓包也都对了。 现在并发上去了，也没丢数据。 我去看看重定向为什么会引起打印不全。 谢谢了。

user: user-1
content: 有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core或dmp文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER     #pragma warning(disable:4996)     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int main(int argc,char * argv[]) {     int i; #ifdef _MSC_VER     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef _MSC_VER     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-79行添加到你带main的.c或.cpp的那个文件的最前面 //81-86行添加到你的main函数开头 //90-94行添加到你的main函数结束前 //在要写LOG的地方仿照第88行的写法写LOG到文件MyLog1.log中

user: user-0
content: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include<fcntl.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <unistd.h> #include <sys/types.h> #include<netinet/tcp.h> //IPPROTO_TCP #include<pthread.h> #include<semaphore.h> #include<time.h> #include <sys/resource.h> #define MAXBUF	    10240 //MAXBUF<=MAXSIZE，MAXBUF用循环read #define MAXSIZE     10240 #define LISTENQ    1000  #define FDSIZE      1000 #define EPOLLEVENTS 100 #define NTHREADS   4   typedef struct { 	int clifd; }recbuf;  typedef struct { 	recbuf *bufs; 	unsigned int max; 	unsigned int front; 	int rear; 	sem_t slots; 	sem_t mutex; 	sem_t items; }sbuf;  sbuf sbufs; int listenfd; int epollfd;  //创建套接字并进行绑定 static void *init_socket(void *arg); //设置socket连接为非阻塞模式 int set_nonblocking(int listenfd); //epoll static void do_epoll(); //写处理 static void do_write(int epollfd,int fd,char *buf); //添加事件 static void add_event(int fd,int state); //修改事件 static void modify_event(int fd,int state); //删除事件 static void delete_event(int fd,int state); //业务处理 static void *thread_do(); //sbuf初始化 static void sbuf_init(sbuf *sp, int n); //sbuf.bufs释放 static void sbuf_destroy(sbuf *sp); //sbuf插入可用连接 static void sbuf_insert(sbuf *sp, int clifd); //sbuf移除可用连接 static void sbuf_remove(sbuf *sp, int *clifd);  int main(int argc,char *argv[]) { 	int i; 	struct rlimit rl; 	pthread_t tid,tid_acc; 	rl.rlim_cur = 10240; 	rl.rlim_max = 10240; 	setrlimit(RLIMIT_NOFILE, &rl); 	getrlimit(RLIMIT_NOFILE, &rl); 	epollfd = epoll_create(FDSIZE); 	pthread_create(&tid_acc,NULL,init_socket,(void*)(argv[1])); 	sbuf_init(&sbufs,100); 	for(i = 0; i < NTHREADS; i++) 	{ 		pthread_create(&tid,NULL,thread_do,NULL); 	} 	do_epoll(); 	close(listenfd); 	sbuf_destroy(&sbufs); 	return 0; }  static void sbuf_init(sbuf *sp, int n) { 	int i; 	if((sp->bufs = (recbuf *)calloc(n,sizeof(recbuf))) == NULL) 	{ 		perror("calloc"); 		exit(1); 	}	 	sp->max = n; 	sp->front = sp->rear = 0; 	sem_init(&sp->slots,0,n); 	sem_init(&sp->mutex,0,1); 	sem_init(&sp->items,0,0); }  static void sbuf_destroy(sbuf *sp) { 	sem_destroy(&sp->slots); 	sem_destroy(&sp->mutex); 	sem_destroy(&sp->items); }  static void sbuf_insert(sbuf *sp, int clifd) { 	int tmp; 	sem_getvalue(&sp->slots,&tmp); 	sem_getvalue(&sp->items,&tmp); 	sem_wait(&sp->slots); 	sp->rear = (sp->rear >= sp->max)?0:sp->rear; 	sp->bufs[sp->rear++].clifd = clifd; 	delete_event(clifd,EPOLLIN); 	sem_post(&sp->items); }  static void sbuf_remove(sbuf *sp, int *clifd) { 	int tmp; 	int tmp1; 	 sem_getvalue(&sp->items,&tmp1); 	 sem_getvalue(&sp->slots,&tmp1); 	sem_wait(&sp->items); 	sem_wait(&sp->mutex); 	sp->front = tmp = (sp->front >= sp->max)?0:sp->front; 	sp->front++; 	sem_post(&sp->mutex); 	*clifd = sp->bufs[tmp].clifd; 	sem_post(&sp->slots); }  static void *thread_do() { 	char buf[MAXBUF]; 	int clifd; 	int nread,n,i,n1; 	pthread_detach(pthread_self()); 	while(1) 	{ 		sbuf_remove(&sbufs, &clifd); 		while(1){ 		n1 = n  = i = 0; 		while((nread = read(clifd,buf+n,MAXBUF-1)) > 0) 		{ 			n += nread; 			i = 1; 		}  		if (nread == -1 && errno != EAGAIN) 		{ 			perror("read error:"); 			close(clifd); 			break; 		} 		else if (i == 0) 		{ 			printf("client close.\n"); 			close(clifd); 			break; 		} 		printf("%s\n",buf); 		write(clifd, buf, strlen(buf)); 		}	  	} }  static void *init_socket(void *arg) { 	int  listenfd, opt = 1, port = atoi((char*)arg); 	struct sockaddr_in servaddr; 	int clifd; 	int val2 = 1460*2; 	int val1; 	struct sockaddr_in cliaddr; 	socklen_t  cliaddrlen = sizeof(struct sockaddr); 	socklen_t  cliaddrlen1 = sizeof(struct sockaddr); 	int val = 2,ret = 0; 	listenfd = socket(AF_INET,SOCK_STREAM,0); 	if (listenfd == -1) 	{ 		perror("socket error:"); 		exit(1); 	} 	bzero(&servaddr,sizeof(servaddr)); 	servaddr.sin_family = AF_INET; 	servaddr.sin_port = htons(port); 	servaddr.sin_addr.s_addr = INADDR_ANY; 	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const void *)&opt,sizeof(opt));   	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const void *)&opt,sizeof(opt));   	setsockopt(listenfd, SOL_SOCKET, SO_RCVBUF, &val2, sizeof(int)); 	setsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, &val2, sizeof(int)); 	getsockopt(listenfd, SOL_SOCKET, SO_RCVBUF, &val1, &cliaddrlen1); 	getsockopt(listenfd, SOL_SOCKET, SO_RCVBUF, &val1, &cliaddrlen1); 	if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1) 	{ 		perror("bind error: "); 		exit(1); 	} 	listen(listenfd,LISTENQ); 	while(1){ 		if((clifd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen)) > 0) 		{ 			set_nonblocking(clifd);		 			printf("accept a new client: %s:%d\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port); 			add_event(clifd,EPOLLIN); 		} 	} }  int set_nonblocking(int listenfd)  { 	int opts; 	opts = fcntl(listenfd, F_GETFL); 	if(opts < 0) { 		perror("fcntl(F_GETFL)\n"); 		return -1; 	} 	opts = (opts | O_NONBLOCK); 	if(fcntl(listenfd, F_SETFL, opts) < 0) { 		perror("fcntl(F_SETFL)\n"); 		return -1; 	} 	return 1; }  static void do_epoll() { 	struct epoll_event events[EPOLLEVENTS]; 	int ret,i; 	while(1) 	{ 		i = 0; 		ret = epoll_wait(epollfd,events,EPOLLEVENTS,2000); 		switch(4<ret){ 			case 1: 				for(i = 0; i< 5;){ 					sbuf_insert(&sbufs,events[i++].data.fd);	 					sbuf_insert(&sbufs,events[i++].data.fd);	 					sbuf_insert(&sbufs,events[i++].data.fd);	 					sbuf_insert(&sbufs,events[i++].data.fd);	 					sbuf_insert(&sbufs,events[i++].data.fd);	 				} 			case 0: 				for(; i< ret;){ 					sbuf_insert(&sbufs,events[i++].data.fd); 				} 				break; 		}  	} 	close(epollfd); }    static void do_write(int epollfd,int fd,char *buf) { 	int nwrite, datalen, n; 	n = datalen = strlen(buf); 	while(n > 0) 	{	 		nwrite = write(fd, buf + datalen - n, n); 		//printf("write to client:%d\n",nwrite); 		if (nwrite < n) 		{ 			if(nwrite == -1 && errno != EAGAIN){	 				perror("write error:"); 				close(fd); 				delete_event(fd,EPOLLOUT); 			} 			break; 		} 		n -= nwrite; 	}  }  static void add_event(int fd,int state) { 	struct epoll_event ev; 	ev.events = state|EPOLLET; 	ev.data.fd = fd; 	epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev); }  static void delete_event(int fd,int state) { 	struct epoll_event ev; 	ev.events = state|EPOLLET; 	ev.data.fd = fd; 	epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev); }  static void modify_event(int fd,int state) { 	struct epoll_event ev; 	ev.events = state|EPOLLET; 	ev.data.fd = fd; 	epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev); }