int main(int argc,char* argv[]) { if(argc !=4) { printf("the args should be ./ELF IP PORT NPthread\n"); exit(-1); } int npthread=atoi(argv[3]); factory_t fact; factory_init(&fact,handle_request,NULL,npthread,0,100); factory_start(&fact,npthread); int lisenfd; lisenfd=socket(AF_INET,SOCK_STREAM,0); if(-1==lisenfd) { perror("socket"); exit(-1); } struct sockaddr_in ser_addr; bzero(&ser_addr,sizeof(struct sockaddr)); ser_addr.sin_family=AF_INET; ser_addr.sin_addr.s_addr=inet_addr(argv[1]); ser_addr.sin_port=htons(atoi(argv[2])); int ret; ret=bind(lisenfd,(struct sockaddr*)&ser_addr,sizeof(struct sockaddr)); if(-1==ret) { perror("bind"); exit(-1); } listen(lisenfd,npthread); struct sockaddr_in client_addr; int len=sizeof(struct sockaddr); int new_sfd; pnode_t pnew; while(1) { bzero(&client_addr,sizeof(struct sockaddr)); new_sfd=accept(lisenfd,(struct sockaddr *)&client_addr,&len); pnew=(pnode_t)malloc(sizeof(node_t)); bzero(pnew,sizeof(node_t)); pnew->sockfd=new_sfd; pthread_mutex_lock(&(fact.s_que).q_mutex); que_set(&fact.s_que,pnew); pthread_mutex_unlock(&(fact.s_que).q_mutex); pthread_cond_signal(&fact.cond); } }
int main(int argc,char* argv[])//主线程函数流程 { if(argc !=5)//传的参数IP PORT NUM QUE_CAPACITY { printf("error args\n"); return -1; } int thread_num=atoi(argv[3]); int capacity=atoi(argv[4]); factory tf;//定义一个线程工厂的结构体, factory_init(&tf,thread_num,capacity,thread_handle);//线程工厂,线程数,能力,线程函数, //先初始再启动,放在factory.c中,主线程中调用数据准备、启动等,主线程主要是写epoll的逻辑 factory_start(&tf);//传地址不仅为了修改数据,也为了节省空间。 //地址只有四个字节,减少栈空间的开销,这里也传结构体进去,但栈空间浪费很大 int sfd=socket(AF_INET,SOCK_STREAM,0); if(-1==sfd) { perror("socket"); return -1; } struct sockaddr_in ser; bzero(&ser,sizeof(ser)); ser.sin_family=AF_INET; ser.sin_port=htons(atoi(argv[2])); ser.sin_addr.s_addr=inet_addr(argv[1]); int ret; ret=bind(sfd,(struct sockaddr *)&ser,sizeof(struct sockaddr)); if(-1==ret) { perror("bind"); return -1; } listen(sfd,capacity);//listen的个数与队列中描述符个数相同 int epfd=epoll_create(1);//创建epoll句柄 struct epoll_event ev,evs[2]; ev.events=EPOLLIN; ev.data.fd=sfd;//这里主要监控的就是sfd,因为子线程与客户端通信完之后是直接去队列中读而不是通知主线程 ret=epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&ev); if(-1==ret) { perror("epoll_ctl"); return -1; } int new_fd; while(1) { ret=epoll_wait(epfd,evs,2,-1); if(ret >0)//代表有客户端连接 { if(evs[0].data.fd==sfd && evs[0].events == EPOLLIN) { new_fd=accept(sfd,NULL,NULL);//如果监控到有请求就接受,接着将new_fd放到队列中,即要写一系列函数 pnode pnew; pnew=(pnode)calloc(1,sizeof(node));//要给指针申请空间之后才能赋值, //calloc默认申请的空间全是null ,如果用malloc,则要先初始化(赋值)null pnew->new_fd=new_fd; factory_que_set(&tf.fd_que,pnew);//将队列操作写到work_que.c中,主线程在放之前, //子线程都处于等待状态,因为前面已经调用子线程流程函数将子线程创建好了 pthread_cond_signal(&tf.cond);//主线程每往队列中放一个,都signal一下 } } } }