UNIX多进程连服务端出现错误
void CreateProcess(int start, int end, func f){ pid_t pid; int client = -1; int loop_times = 0; int fd = open(ERRLOG, O_CREAT|O_RDWR|O_APPEND); close(fd); fd = open(SENDLOG, O_CREAT|O_RDWR|O_APPEND); close(fd); fd = open(RECEIVELOG, O_CREAT|O_RDWR|O_APPEND); close(fd); struct sigaction old; struct sigaction new; new.sa_handler = ChildExit; new.sa_flags |= SA_RESTART; sigemptyset(&new.sa_mask); while(start <= end) { pid=fork(); if(pid == 0 || pid == -1) { break; } sigaction(SIGCHLD, &new, &old); usleep(50000); start++; } if(pid == -1) { Log(ERRLOG,FormatString("Create process failed:%s", strerror(errno))); exit(EXIT_FAILURE); } if(pid == 0) { int client = 0; while(1) { client = Process(start); if(client != 0) { break; } loop_times++; printf("%d:connect failed.After %d s continue...\n", getpid(), loop_times); sleep(loop_times); if(loop_times > 100) { Log(ERRLOG, FormatString("%s:Create socket failed",itoa(getpid()),strerror(errno))); exit(EXIT_FAILURE); } } if(f(client, start)) { close(client); exit(EXIT_SUCCESS); } else { printf("%d:error\n", getpid()); close(client); exit(EXIT_FAILURE); } }}void ChildExit(int sig){ pid_t pid; int status; while((pid = waitpid(-1 , &status, WNOHANG)) > 0) { if(WIFEXITED(status)) { if(WEXITSTATUS(status) == EXIT_SUCCESS) { printf("%d exit success...\n", pid); } else { printf("%d exit failed:%d...\n", pid, status); } } else { printf("%d occur error:%s\n", pid, strerror(errno)); Log(ERRLOG, FormatString("%s occur error:%s\n", itoa(pid), strerror(errno))); } }}int Process(int start){ printf("%d:start\n", getpid()); int client = CreateSocket(); if(!client) { return 0; } if(!ConnectServer(client)) { return 0; } return client;}int CreateSocket(){ int client = socket(AF_INET, SOCK_STREAM, 0); if(client == -1) { return 0; } return client;}int ConnectServer(int client){ struct sockaddr_in servaddr; socklen_t socklen = sizeof(servaddr); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_aton(HOST, &servaddr.sin_addr); servaddr.sin_port = htons(PORT); if(connect(client, (struct sockaddr *)&servaddr, socklen) == -1) { return 0; } return 1; }
[解决办法]
其实这个单进程就足够了, epoll+非阻塞connect, 很快就秒掉了。
假设你非要多进程单线程的模型拉做这个事情, 实在就拿你没办法了... 你这个也就能造成个几千的并发压力, 再高系统也不让你创建那么多进程了.
你应该是进程池的工作模式, 每个子进程不断的请求, 直到总请求次数全部结束.
一看这个需求, 就知道各个进程之间要共享一个计数, 很明显共享内存里面放一个计数就行了, 每个子进程开始请求之前加锁检查一下是否全部完成,还没全部完成就-1,解锁开始请求,否则退出进程,就这么回事.
父进程的做法比较多, 其实就是所有子进程都主动退出了, 那么说明所有的任务都完成了。
所以,父进程阻塞在那里wait就行了,一直到所有子进程退出。
但是,如果想让程序实用一点,也就是打印请求进度,并且支持用户操控信号,那么阻塞wait就不合适了,怎么办? 让父进程轮询,在轮询里加锁检查计数以便打印进度,并且在轮询里waitpid非阻塞回收子进程,一直到所有子进程都退出了,那父进程就可以退出了。