多进程并发服务器
设计流程
框架一(使用信号回收僵尸进程)
void handler(int sig)
{while(waitpid(-1, NULL, WNOHANG) > 0);
}int main()
{siganl(17, handler);server = socket();bind();listen();while(1){client = accept();if(fork() == 0){close(server);while(1){recv();send();}close(client);exit(0);}close(client);}close(server);
}
实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);void cil(int client, struct sockaddr_in caddr);void handler(int sig)
{while(waitpid(-1, NULL, WNOHANG) > 0);
}int main(int argc, char *argv[])
{signal(17, handler);int server = -1;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8888);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("Tcp server start success");int client = -1;struct sockaddr_in caddr = {0};socklen_t len = sizeof(caddr);pid_t pid = -1;while(1){if((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1){LOG("accpet error");return -1;}printf("[%s/%d] client已上线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));if((pid = fork()) < 0){LOG("fork error");return -1;}else if(pid == 0){cil(client, caddr);exit(0);}close(client);}close(server);return 0;
}void cil(int client, struct sockaddr_in caddr)
{char buf[128] = "";int res = 0;while(1){bzero(buf, sizeof(buf));if((res = read(client, buf, sizeof(buf))) < 0){LOG("read error");break;}else if(res == 0){printf("[%s/%d] client已下线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));close(client);break;}printf("[%s/%d] client: %s\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port), buf);bzero(buf, sizeof(buf));strcpy(buf, "ok");if(write(client, buf, sizeof(buf)) < 0){LOG("write error");break;}}}
框架二(使用孤儿进程机制避免僵尸进程产生)
int main()
{server = socket();bind();listen();while(1){if((pid = fork()) == 0){client = accept();if(pid = fork() == 0){while(1){recv();send();}close(client);exit(0);}else if(pid > 0){close(server);close(client);exit(0);}}else if(pid > 0){while(waitpid() == pid)}}close(server);
}
实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s\n", __DATE__, __FILE__, __LINE__, s);void deal_cil_msg(int client, struct sockaddr_in caddr);int main(int argc, char *argv[])
{int server = 0;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8888);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("server start success");struct sockaddr_in caddr = {0};int client = 0;socklen_t asize = sizeof(caddr);pid_t pid = -1;int status = 0;while(1){pid = fork();if(pid < 0){LOG("fork error");return -1;}if(pid == 0){if((client = accept(server, (struct sockaddr*)&caddr, &asize)) == -1){LOG("accept error");return -1;}printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));pid = fork();if(pid < 0){LOG("fork error");return -1;}else if(pid == 0){deal_cil_msg(client, caddr);close(client);exit(0);}else if(pid > 0){close(server);close(client);exit(0);}}else if(pid > 0){printf("wait child = %d\n", pid);while(waitpid(pid, &status, 0) == pid){printf("Parent is over - child: %d, status = %x\n", pid, status);}}}close(server);return 0;
}void deal_cil_msg(int client, struct sockaddr_in caddr)
{char buf[128] = " ";while(1){int len = 0;bzero(buf, sizeof(buf));if((len = recv(client, buf, sizeof(buf), 0)) < 0){ LOG("recv error");}else if(len == 0){printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));break;}printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);bzero(buf, sizeof(buf));strcpy(buf, "ok");write(client, buf, len);}}
多线程并发服务器
设计流程
typedef struct
{int client;struct sockaddr_in caddr;
} Client_msg;int main()
{server = socket();bind();listen();while(1){client = accpet();pthread_create();while(1){}pthread_detach();}close(server);
}
实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);void* cil(void* arg);
typedef struct
{int client;struct sockaddr_in caddr;
} Cli_msg;int main(int argc, char *argv[])
{int server = -1;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8899);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("tcp server start success");struct sockaddr_in caddr = {0};socklen_t len = sizeof(caddr);pthread_t tid = -1;int client = -1;Cli_msg cli_msg;while(1){if((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1){LOG("accept error");return -1;}printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));cli_msg.client = client;cli_msg.caddr = caddr;if(pthread_create(&tid, NULL, cil, &cli_msg) != 0){LOG("pthread_create error");return -1;}pthread_detach(tid);}close(server);return 0;
}void* cil(void* arg)
{int client = ((Cli_msg*)arg)->client;struct sockaddr_in caddr = ((Cli_msg*)arg)->caddr;char buf[128] = "";int res = 0;while(1){bzero(buf, sizeof(buf));if((res = read(client, buf, sizeof(buf))) < 0){LOG("read error");break;}else if(res == 0){printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));close(client);pthread_exit(NULL);}printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);bzero(buf, sizeof(buf));strcpy(buf, "ok");if(write(client, buf, sizeof(buf)) < 0){LOG("write error");break;}}}