我用一个线程监听,如果有数据可读,就通知另一个线程去读。下面是监听线程的代码。出现的问题就是三次握手后,服务端就自动发送了一个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);
}