多线程
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>#include <netinet/ip.h>#include <arpa/inet.h>#include <sys/un.h>#include <ctype.h>#include "wrap.h"#include <signal.h>#include <sys/wait.h>#define LISTEN_BACKLOG 50#define EXIT_FAILURE 1#define SERVICE_PORT 2222void* thread_func(void* arg){ /*处理请求*/ int cfd=(int)arg; char buffer[BUFSIZ]; int ret=read(cfd,buffer,BUFSIZ); write(STDOUT_FILENO,buffer,ret); for(int i=0;i<ret;i++){ buffer[i]=toupper(buffer[i]); } write(cfd,buffer,ret); close(cfd); //关闭连接套接字 return NULL;}/* 用于其他线程回收线程 */void* garbage_collection(void* arg){ pthread_t *pid=(pthread_t*)arg; pthread_join(*pid,NULL); pthread_detach(pthread_self()); return NULL;}int main(int argc,char *argv[]){ int lfd,cfd; pthread_t tid,gid; struct sockaddr_in srv_addr,client_addr; char client_ip_addr[20]; socklen_t client_addr_size; /* 创建套接字 */ lfd=Socket(AF_INET,SOCK_STREAM,0); /* 创建服务器地址 */ memset(&srv_addr,0,sizeof(struct sockaddr_in)); srv_addr.sin_family=AF_INET; srv_addr.sin_port=htons(SERVICE_PORT); srv_addr.sin_addr.s_addr=htonl(INADDR_ANY); /*端口复用*/ int optval=1; setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(optval)); /* 绑定 */ Bind(lfd,(struct sockaddr*)&srv_addr,sizeof(srv_addr)); /* 设置监听上限 */ Listen(lfd,LISTEN_BACKLOG); client_addr_size=sizeof(struct sockaddr_in); while(1){ /* 等待连接 */ cfd=Accept(lfd,(struct sockaddr*)&client_addr,&client_addr_size); //将IP地址转换为点分十进制 inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr)); printf("new client coming! ip: %s port %d \n",client_ip_addr,ntohs(client_addr.sin_port)); /*创建线程*/ int create_ret=pthread_create(&tid,NULL,thread_func,(void*)cfd); if(create_ret!=0) perr_exit("join error"); pthread_create(&gid,NULL,garbage_collection,(void*)&tid); continue; }#ifdef DEBUGLOG printf("client info: ip: %s port %d \n", inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr)) ,client_addr.sin_port);#endif return 0;}
多进程
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>#include <netinet/ip.h>#include <arpa/inet.h>#include <sys/un.h>#include <ctype.h>#include "wrap.h"#include <signal.h>#include <sys/wait.h>#define LISTEN_BACKLOG 50#define EXIT_FAILURE 1#define SERVICE_PORT 2222void Sig_handle(int signo){ if(signo==SIGCHLD){ pid_t ret; int state; while((ret=waitpid(-1,&state,WNOHANG))!=-1){ if(ret!=0 && WIFEXITED(state)){ printf("child %d finish the task with exit state %d\n",ret,WEXITSTATUS(state)); } } }}int main(int argc,char *argv[]){ int lfd,cfd; pid_t pid; struct sockaddr_in srv_addr,client_addr; char client_ip_addr[20]; socklen_t client_addr_size; /* 信号相关 */ sigset_t set,oldset; sigemptyset(&set); sigaddset(&set,SIGCHLD); /* 创建套接字 */ lfd=Socket(AF_INET,SOCK_STREAM,0); /* 创建服务器地址 */ memset(&srv_addr,0,sizeof(struct sockaddr_in)); srv_addr.sin_family=AF_INET; srv_addr.sin_port=htons(SERVICE_PORT); srv_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 绑定 */ Bind(lfd,(struct sockaddr*)&srv_addr,sizeof(srv_addr)); /* 设置监听上限 */ Listen(lfd,LISTEN_BACKLOG); client_addr_size=sizeof(struct sockaddr_in); while(1){ /* 等待连接 */ cfd=Accept(lfd,(struct sockaddr*)&client_addr,&client_addr_size); printf("new client coming! ip: %s port %d \n", inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr)) ,client_addr.sin_port); // sigprocmask(SIG_BLOCK,&set,&oldset); pid=Fork(); if(pid==0){//child close(lfd); //关闭监听套接字 /*处理请求*/ char buffer[BUFSIZ]; int ret=read(cfd,buffer,BUFSIZ); write(STDOUT_FILENO,buffer,ret); for(int i=0;i<ret;i++){ buffer[i]=toupper(buffer[i]); } write(cfd,buffer,ret); close(cfd); //关闭连接套接字 }else if(pid>0){ close(cfd); struct sigaction act; /*信号回收子进程*/ sigemptyset(&act.sa_mask); act.sa_flags=0; act.sa_handler=Sig_handle; int sig_ret=sigaction(SIGCHLD,&act,NULL); if(sig_ret!=0) perr_exit("sigaction"); // sigprocmask(SIG_SETMASK,&oldset,NULL); continue; } }#ifdef DEBUGLOG printf("client info: ip: %s port %d \n", inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr)) ,client_addr.sin_port);#endif return 0;}