- 论坛徽章:
- 1
|
本帖最后由 lewy7 于 2014-02-15 21:02 编辑
现在碰到个问题,
当客户端a 在与服务短s 通信过中异常断开后,再有新客户端b连接进来的时候,会读到上个客户端a的发数据,而不是读到客户端b的发数据。
如果再有客户端c连接到服务端s的时候,读到的又是客户端b发送的数据。
还有一个更棘手的问题,当出现上面这种情况的时候,服务端会出现CLOSE_WAIT,并且持续很久,而且新连接进来的客户端有很大几率连接不进服务端。
这一般是什么原因,怎么处理?
有哪位帮看一下,感激不尽
贴代码- #define LISTEN_BACKLOG 511
- #define EPOLL_MAX_EVENTS 1000
- #define EPOLL_TIMEOUT 500
- #define EPOLL_SIZE 1024
- #define BIG_BUFF_SIZE 4096
- #define CONTENT_LEN 10 //长度信息所占长度
- typedef struct ep_container_s ep_container_t;
- struct ep_container_s
- {
- int fd;
- char ibuf[BIG_BUFF_SIZE];
- char obuf[BIG_BUFF_SIZE];
- int ilen;
- int ioffset;
- int olen;
- int ooffset;
- };
- void ms_tcp_working()
- {
- int epollfd;
- int fds;
- int sfd;
- int clientfd;
- int i,ret;
- int errinfo;
- int cork;
- struct linger so_linger;
- struct epoll_event ev,events[EPOLL_MAX_EVENTS];
- ep_container_t ep_c;
- ep_container_t *ep_c_ptr;
-
- epollfd=epoll_create(EPOLL_SIZE);
- ev.data.fd=_tcp_param.listenfd;
- ev.events=EPOLLIN|EPOLLET;
- epoll_ctl(epollfd,EPOLL_CTL_ADD,_tcp_param.listenfd,&ev);
-
- while(1)
- {
- fds=epoll_wait(epollfd,events,EPOLL_MAX_EVENTS,EPOLL_TIMEOUT);
- for(i=0;i<fds;++i)
- {
- if(events[i].data.fd == _tcp_param.listenfd)
- {
- printf("client connect\n");
- clientfd = accept(_tcp_param.listenfd,NULL,NULL);
- if(clientfd<0 )
- {
- if(EAGAIN==errno)//忽略惊群
- {
- printf("EAGAIN%d\n",getpid());
- continue;
- }
- else
- {
- perror("accept err:");
- exit(1);
- }
- }
- ms_tcp_set_nonblocking(clientfd);//设置非阻塞
- so_linger.l_onoff = 1;
- so_linger.l_linger = 2;
- setsockopt(clientfd,SOL_SOCKET,SO_LINGER,&so_linger,sizeof(struct linger));
- printf("clientfd=[%d]\n",clientfd);
- //添加用于读操作的文件描述符
- ep_c_ptr=(ep_container_t *)malloc(sizeof(ep_container_t));
- ep_c_ptr->fd = clientfd;
- ep_c_ptr->ioffset = 0;//记录已经收到客户端发送的字节数
- ep_c_ptr->ilen = 0;//记录接收 头部10个字节的长度信息
- ep_c_ptr->olen = 0;
- ep_c_ptr->ooffset = 0;
- ev.data.ptr = ep_c_ptr;
- ev.events=EPOLLIN|EPOLLET;
- ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,clientfd,&ev);
- }
- else if(events[i].events&EPOLLIN)
- {
- printf("EPOLLIN\n");
- ep_c_ptr = (ep_container_t *)events[i].data.ptr;
- sfd = ep_c_ptr->fd;
- while(1)//本次循环读取,一直读到EAGAIN
- {
- printf("rr ep_c_ptr->ioffset=[%d]\n",ep_c_ptr->ioffset);
- ret = read(sfd, ep_c_ptr->ibuf+ep_c_ptr->ioffset, BIG_BUFF_SIZE);
- if(0 == ret || -1 == ret && errno == EAGAIN || -1 == ret && errno == ECONNRESET || -1 == ret &&errno==ETIMEDOUT)
- {
- errinfo = errno;
- break;
- }
- if(ret >0)
- {
- ep_c_ptr->ioffset += ret;
- continue;
- }
- }
- if(ECONNRESET == errinfo && -1 == ret || 0 ==ret || -1 == ret &&errinfo==ETIMEDOUT)
- {
- free(events[i].data.ptr);
- events[i].data.ptr = NULL;
- epoll_ctl(epollfd,EPOLL_CTL_DEL,sfd,NULL);
- printf("close-----[%d][%d]ret[%d]\n",getpid(),sfd,ret);
- close(sfd);
- continue;
- }
- else if (-1 == ret && errinfo == EAGAIN )//本次读取 完毕
- {
- if( 0 == ep_c_ptr->ilen)//取头部长度信息
- {
- ep_c_ptr->ilen = ms_tcp_leninfo(ep_c_ptr->ibuf);
- }
- if(ep_c_ptr->ilen > ep_c_ptr->ioffset+CONTENT_LEN)
- {
- //继续将文件描述符加入可读事件队列
- printf("cc ep_c_ptr->ioffset=[%d]\n",ep_c_ptr->ioffset);
- ev.data.ptr = ep_c_ptr;
- ev.events=EPOLLIN|EPOLLET;
- if(-1 == epoll_ctl(epollfd,EPOLL_CTL_MOD,sfd,&ev))
- {
- perror("epoll_ctl err:EPOLL_CTL_MOD");
- free(ep_c_ptr);
- close(sfd);
- }
- }
- else
- {
- printf("pid%drecv=[%d][%d][%s]\n",getpid(),ep_c_ptr->ilen,ep_c_ptr->ioffset,ep_c_ptr->ibuf);
- //将文件描述符加入可写事件队列
- ev.data.ptr = ep_c_ptr;
- ev.events=EPOLLOUT|EPOLLET;
- if(-1 == epoll_ctl(epollfd,EPOLL_CTL_MOD,sfd,&ev))
- {
- perror("epoll_ctl err:EPOLL_CTL_MOD");
- free(ep_c_ptr);
- close(sfd);
- }
- }
- continue;//继续循环
-
- }
- }
- else if(events[i].events&EPOLLOUT)
- {
- printf("EPOLLOUT\n");
- ep_c_ptr = (ep_container_t *)events[i].data.ptr;
- sfd = ep_c_ptr->fd;
- strcpy(ep_c_ptr->obuf,"0000000005aaaax");
- if(ep_c_ptr->ooffset == 0)
- ep_c_ptr->olen=5;
-
- ret=write(sfd, ep_c_ptr->obuf+ep_c_ptr->ooffset, ep_c_ptr->olen+CONTENT_LEN);
- if(ret>0)
- {
- printf("write[%d]\n",ret);
- ep_c_ptr->ooffset += ret;
- if(ep_c_ptr->ooffset == ep_c_ptr->olen+CONTENT_LEN)//写入完毕 短连接关闭
- {
- free(ep_c_ptr);
- if(-1 ==epoll_ctl(epollfd,EPOLL_CTL_DEL,sfd,NULL))
- {
- perror("epoll_ctl err:EPOLL_CTL_DEL");
- }
- close(sfd);
- continue;
- }
- else //没有写完,继续将文件描述符加入可写事件队列
- {
- ev.data.ptr = ep_c_ptr;
- ev.events=EPOLLOUT|EPOLLET;
- if(-1 == epoll_ctl(epollfd,EPOLL_CTL_MOD,sfd,&ev))
- {
- perror("epoll_ctl err:EPOLL_CTL_MOD");
- free(ep_c_ptr);
- close(sfd);
- continue;
- }
-
- }
-
- }
- //继续将文件描述符加入可写事件队列
- else if(ret < 0 && errno == EINTR || ret < 0 && errno == EAGAIN || ep_c_ptr->ooffset < ep_c_ptr->olen+CONTENT_LEN)
- {
- ev.data.ptr = ep_c_ptr;
- ev.events=EPOLLOUT|EPOLLET;
- if(-1 == epoll_ctl(epollfd,EPOLL_CTL_MOD,sfd,&ev))
- {
- perror("epoll_ctl err:EPOLL_CTL_MOD");
- free(ep_c_ptr);
- close(sfd);
- continue;
- }
- }
- else //其它错误的话就关闭端口,释放资源
- {
- perror("write err");
- close(sfd);
- free(ep_c_ptr);
- continue;
- }
- }
- }
- }
-
- }
复制代码 |
|