/*
*
*EPOLL ET 触发必须使用非阻塞,LT触发可以阻塞/非阻塞。
*read 函数 非阻塞读需 忙轮寻 soket关闭返回0,循环读完数据
*如果已经读完再读read返回 -1,errno=11(EAGIAN)则退出轮循
*
**/
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/select.h>
#include<sys/time.h>
#include<pthread.h>
#include<memory.h>
#include<errno.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<semaphore.h>
#include<malloc.h>
#include<fcntl.h>
#include<sys/epoll.h>
typedef unsigned int uint32;
pthread_mutex_t lock;
uint32 qcount=0;
typedef struct{
int flag;
sem_t sem;
}MYLOCK;
struct sockaddr_in server;
MYLOCK mlock;
int g_epfd=-1;
void printerror()
{
printf("%d:%s\n",errno,strerror(errno));
exit(-1);
}
void* th_hand(void* p){
sem_wait(&mlock.sem);
while(!mlock.flag){
sem_post(&mlock.sem);
sleep(1);
sem_wait(&mlock.sem);
}
sem_post(&mlock.sem);
struct epoll_event events[10];
struct epoll_event event;
while(1){
memset(&event,0,sizeof(struct epoll_event));
memset(events,0,sizeof(struct epoll_event)*10);
int s = epoll_wait(g_epfd,events,10,100);
if(s==-1){
printerror();
}else if(s==0){
continue;
}else if(s>0){
for(int i=0;i<s;i++){
int fd=events[i].data.fd;
char buff[4];
while(1){
int rd=-1;
memset(buff,0,sizeof(buff));
rd=read(fd,buff,sizeof(buff)-1);
if(rd==0){
struct sockaddr_in client;
memset(&client,0,sizeof(client));
int len=sizeof(client);
getpeername(fd,(struct sockaddr*)&client,&len);
printf("client %s is closed fd is %d , bye!\n",inet_ntoa(client.sin_addr),fd);
close(fd);
event.data.fd=fd;
sem_post(&mlock.sem);
epoll_ctl(g_epfd,EPOLL_CTL_DEL,fd,&event);
sem_wait(&mlock.sem);
break;
}else if(rd>0){
int wr=write(STDOUT_FILENO,buff,rd);
}else if(rd==-1){
if(errno==EAGAIN)
break;
printerror();
}
}
}
}
}
}
int initSocket(int port){
memset(&server,0,sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=htonl(INADDR_ANY);//INADDR_ANY==0
server.sin_port=htons(port);
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1){
printerror();
}
int res=bind(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr));
if(res==-1){
printerror();
}
if(-1==listen(sockfd,10)){
printerror();
}
g_epfd=epoll_create(5);
if(g_epfd==-1){
printerror();
}
sem_wait(&mlock.sem);
mlock.flag=1;
sem_post(&mlock.sem);
printf("main before accept\n");
while(1){
int fd;
if((fd=accept(sockfd,NULL,NULL))==-1){
printerror();
}
printf("fd %d is connect\n",fd);
struct epoll_event event;
// event.events=EPOLLIN;
event.events=EPOLLIN|EPOLLET;
event.data.fd=fd;
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK);
sem_wait(&mlock.sem);
if(-1==(epoll_ctl(g_epfd,EPOLL_CTL_ADD,fd,&event))){
printerror();
}
qcount++;
sem_post(&mlock.sem);
}
}
void sig_hand(int signo){
if(signo==SIGINT){
printf("have %d client\n",qcount);
exit(0);
}
}
pthread_t pid;
int main(int argc,char** argv){
if(argc<2){
puts("please input port\n");
exit(-1);
}
int port=atoi(argv[1]);
signal(SIGINT,sig_hand);
memset(&mlock,0,sizeof(mlock));
sem_init(&mlock.sem,0,1);
mlock.flag=0;
pthread_create(&pid,NULL,th_hand,(void*)0);
pthread_detach(pid);
initSocket(port);
}