多线程
#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 2222
void* 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 2222
void 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;
}