多进程服务器端
并发服务器实现模型和方法主要有三种:
(1)多进程服务器端:通过创建多个进程提供服务
(2)多路复用服务器:通过捆绑并统一管理IO对象提供服务
(3)多线程服务器:通过生成与客户端等量的线程提供服务
用sigaction信号处理技术消灭僵尸进程。(这里不详述)
多进程服务器端实现echo服务器。
每当客户端请求服务时,回声服务器就创建子进程以提供服务。步骤如下:
(1)回声服务器端(父进程)通过调用accept函数处理连接请求
(2)此时获取的套接字文件描述符创建并传递给子进程
(3)子进程利用传递来的文件描述符提供服务
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 30
void read_childproc(int sig);
int main(int argc,char *argv[])
{
//create the socket,bind,listen,accept
//create the signal,avoid zombi process
//use fork to create child process for each client
int serv_sock,clnt_sock;
struct sockaddr_in serv_adr,clnt_adr;
pid_t pid;
socklen_t adr_sz;
int str_len,state;
char buf[BUF_SIZE];
struct sigaction act;
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
state=sigaction(SIGCHLD,&act,0);
serv_sock=socket(PF_INET,SOCK_STREAM,0);
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
if(bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr))==-1)
printf("bind error");
if(listen(serv_sock,5)==-1)
printf("listen error");
while(1)
{
adr_sz=sizeof(clnt_adr);
clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&adr_sz);
if(clnt_sock==-1) continue;
else puts("new client connected....");
pid=fork();
if(pid==-1)
{
close(clnt_sock);continue;
}
if(pid==0)
{
close(serv_sock);
while((str_len=read(clnt_sock,buf,BUF_SIZE))!=0)
write(clnt_sock,buf,str_len);
close(clnt_sock);
puts("client disconnected");
return 0;
}
else
{
close(clnt_sock);
}
}
close(serv_sock);
return 0;
}
void read_childproc(int sig)
{
pid_t pid;
int status;
pid=waitpid(-1,&status,WNOHANG);
printf("remove proc id : %d\n",pid);
}
多进程客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
int main(int argc,char *argv[])
{
int sock;
char message[BUF_SIZE];
int str_len;
struct sockaddr_in serv_adr;
sock=socket(PF_INET,SOCK_STREAM,0);
if(sock==-1)
{
printf("error socket");
}
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
serv_adr.sin_port=htons(atoi(argv[2]));
if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)
printf("connect error");
else printf("connect");
while(1)
{
fputs("INPUT message (Q to quit):",stdout);
fgets(message,BUF_SIZE,stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
break;
write(sock,message,strlen(message));
str_len=read(sock,message,BUF_SIZE-1);
message[str_len]=0;
printf("MESSAGE from server: %s",message);
}
close(sock);
return 0;
}