int ser_prend(t_env *env, t_fd *fd, char *cmd) { t_square *sq; int quantity_sq; t_resource res; sq = get_square(env, fd->trantor.pos_x, fd->trantor.pos_y); res = str_to_resource(cmd + 6); quantity_sq = nb_res_in_inventory(&sq->content, res); if (quantity_sq < 1) { send_cmd_to_client(fd, MSG_KO); return (-1); } add_resource(&fd->trantor.inventory, res); del_resource(&sq->content, res); send_infos(env, fd, res); return (0); }
int main( int argc, char* argv[] ) { if( argc <= 2 ) { printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); for( int i = 0; i < PROCESS_COUNT; ++i ) { ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sub_process[i].pipefd ); assert( ret != -1 ); sub_process[i].pid = fork(); if( sub_process[i].pid < 0 ) { continue; } else if( sub_process[i].pid > 0 ) { close( sub_process[i].pipefd[1] ); setnonblocking( sub_process[i].pipefd[0] ); continue; } else { close( sub_process[i].pipefd[0] ); setnonblocking( sub_process[i].pipefd[1] ); run_child( i ); exit( 0 ); } } epoll_event events[ MAX_EVENT_NUMBER ]; epollfd = epoll_create( 5 ); assert( epollfd != -1 ); addfd( epollfd, listenfd ); ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sig_pipefd ); assert( ret != -1 ); setnonblocking( sig_pipefd[1] ); addfd( epollfd, sig_pipefd[0] ); addsig( SIGCHLD, sig_handler ); addsig( SIGTERM, sig_handler ); addsig( SIGINT, sig_handler ); addsig( SIGPIPE, SIG_IGN ); bool stop_server = false; int sub_process_counter = 0; while( !stop_server ) { int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 ); if ( ( number < 0 ) && ( errno != EINTR ) ) { printf( "epoll failure\n" ); break; } for ( int i = 0; i < number; i++ ) { int sockfd = events[i].data.fd; if( sockfd == listenfd ) { int new_conn = 1; send( sub_process[sub_process_counter++].pipefd[0], ( char* )&new_conn, sizeof( new_conn ), 0 ); printf( "send request to child %d\n", sub_process_counter-1 ); sub_process_counter %= PROCESS_COUNT; } else if( ( sockfd == sig_pipefd[0] ) && ( events[i].events & EPOLLIN ) ) { int sig; char signals[1024]; ret = recv( sig_pipefd[0], signals, sizeof( signals ), 0 ); if( ret == -1 ) { continue; } else if( ret == 0 ) { continue; } else { for( int i = 0; i < ret; ++i ) { switch( signals[i] ) { case SIGCHLD: { pid_t pid; int stat; while ( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 ) { for( int i = 0; i < PROCESS_COUNT; ++i ) { if( sub_process[i].pid == pid ) { close( sub_process[i].pipefd[0] ); sub_process[i].pid = -1; } } } stop_server = true; for( int i = 0; i < PROCESS_COUNT; ++i ) { if( sub_process[i].pid != -1 ) { stop_server = false; } } break; } case SIGTERM: case SIGINT: { printf( "kill all the clild now\n" ); for( int i = 0; i < PROCESS_COUNT; ++i ) { int pid = sub_process[i].pid; kill( pid, SIGTERM ); } break; } default: { break; } } } } } else { continue; } } } del_resource(); return 0; }
int main(int argc ,char* argv[]) { if(argc <= 2) { printf("usage : %s ip_address port_number \n",argv[0]); return 1; } const char* ip = argv[1]; int port = atoi(argv[2]); int ret =0; struct sockaddr_in address; bzero(&address,sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port = htons(port); listenfd = socket(PF_INET,SOCK_STREAM,0); assert(listenfd >= 0); ret = bind(listenfd,(struct sockaddr*) &address,sizeof(address)); assert(ret != -1); ret = listen(listenfd,5); assert(ret != -1); user_count = 0; users = (client_data *) malloc(sizeof(client_data)*(USER_LIMIT+1)); sub_process = (int *)malloc(sizeof(int)*(PROCESS_LIMIT+1)); int i = 0; for(; i<PROCESS_LIMIT;++i) { sub_process[i] = -1; } struct epoll_event events[MAX_EVENT_NUMBER]; epollfd = epoll_create(5); assert(epollfd != -1); addfd(epollfd,listenfd); ret = socketpair(PF_UNIX,SOCK_STREAM,0,sig_pipefd); assert(ret != -1); setnonblocking(sig_pipefd[1]); addfd(epollfd,sig_pipefd[0]); addsig(SIGCHLD,sig_handler,true); addsig(SIGTERM,sig_handler,true); addsig(SIGINT,sig_handler,true); addsig(SIGPIPE,SIG_IGN,true); bool stop_server = false; bool terminate = false; shmfd = shm_open(shm_name,O_CREAT|O_RDWR,0666); assert(shmfd != -1); ret = ftruncate(shmfd,USER_LIMIT*BUFFER_SIZE); assert(ret != -1); share_mem = (char*) mmap(NULL,USER_LIMIT*BUFFER_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,shmfd,0); assert(share_mem != MAP_FAILED); close(shmfd); while(!stop_server) { int number = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1); if((number <0) && (errno != EINTR)) { printf("epoll failure\n"); break; } int i = 0; for(;i<number;i++) { int sockfd = events[i].data.fd; // 处理客户端链接请求 if(sockfd == listenfd) { struct sockaddr_in client_address; socklen_t client_addrlength = sizeof(client_address); int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength); if(connfd < 0) { printf("errno is :%d\n",errno); continue; } if(user_count >= USER_LIMIT) { const char* info ="too many users\n"; printf("%s",info); send(connfd,info,strlen(info),0); close(connfd); continue; } users[user_count].address = client_address; users[user_count].connfd = connfd; ret = socketpair(PF_UNIX,SOCK_STREAM,0,users[user_count].pipefd); assert(ret != -1); pid_t pid = fork(); if(pid <0) { close(connfd); continue; } else if(pid == 0) { close(epollfd); close(listenfd); close(users[user_count].pipefd[0]); close(sig_pipefd[0]); close(sig_pipefd[1]); run_child(user_count,users,share_mem); munmap((void*)share_mem,USER_LIMIT*BUFFER_SIZE); exit(0); } else { close(connfd); close(users[user_count].pipefd[1]); addfd(epollfd,users[user_count].pipefd[0]); users[user_count].pid = pid; sub_process[pid]= user_count; user_count ++; } } // 处理信号事件 else if( sockfd == sig_pipefd[0] && (events[i].events & EPOLLIN)) { int sig; char signals[1024]; ret = recv(sig_pipefd[0],signals,sizeof(signals),0); if( ret == -1) { continue; } else if ( ret == 0) { continue; } else { int i=0; for ( ;i< ret; ++i) { switch(signals[i]) { case SIGCHLD: { pid_t pid; int stat; while(( pid = waitpid(-1,&stat,WNOHANG)) > 0) { /* 用子进程pid获取关闭的客户端的编号 * */ int del_user = sub_process[pid]; sub_process[pid] = -1; if((del_user < 0) || (del_user> USER_LIMIT)) { continue; } //清除此客户链接使用的相关数据,更新user和sub_process数组 epoll_ctl(epollfd,EPOLL_CTL_DEL,users[del_user].pipefd[0],0); close(users[del_user].pipefd[0]); users[del_user]= users[--user_count]; sub_process[users[del_user].pid] = del_user; } if(terminate && user_count == 0) { stop_server = true; } break; } case SIGTERM: case SIGINT: { printf("kill all the child now \n"); if(user_count ==0) { stop_server = true; break; } int i=0; for(;i<user_count;++i) { int pid = users[i].pid; kill(pid,SIGTERM); } terminate = true; break; } default: { break; } } } } } else if(events[i].events & EPOLLIN) { int child = 0; ret = recv(sockfd,(char*)&child,sizeof(child),0); printf("read data from child accross pipe\n"); if(ret == -1) { continue; } else if (ret ==0) { continue; } else { int j =0; for( ;j<user_count;++j) { if(users[j].pipefd[0] != sockfd) { printf("send data to child accross pipe\n"); send(users[j].pipefd[0],(char*)&child,sizeof(child),0); } } } } } } del_resource(); return 0; }