/*************************************************************************
> File Name: multi_process_server.c
> Author: xuchen_allen
> Mail: [email protected]
> Created Time: 2019年02月10日 星期日 18时59分17秒
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<signal.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/socket.h>
#define SER_PORT 8080
void do_sigchld(int mun)
{
while(waitpid(0,NULL,WNOHANG)>0);
}
int main(void)
{
//创建套接字:
struct sockaddr_in ser_add,cli_add;
socklen_t cli_add_len;
char buf[2048];
char str[128];
int i,n;
pid_t pid;
//进行信号处理:
sigset_t myset; //定义一个信号集;
sigemptyset(&myset);//初始化该信号集,此时里面没有任何信号;
sigaddset(&myset,SIGCHLD);//将SIGCHLD加入到信号集中,再对其进行操作;
sigprocmask(SIG_BLOCK,&myset,NULL);//将信号集的信号都设定为阻塞状态,这样父进程就不会默认处理SIGCHLD信号(忽略),此时将SIGCHLD放入未决信号表,等待处理;
printf("SIGCHLD is BLOCK.\n");
//指定期望的网络协议类型:
int listenfd = socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0){
perror("socket fail");
exit(1);
}
printf("socket success.\n");
//设置端口复用:
int opt = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
//设置端口复用,是为了防止主动断开连接端的TIME_WAIT状态导致断开连接后的2MSL时间内不能重联;
//对ser_adr进行初始化:
bzero(&ser_add,sizeof(ser_add));
ser_add.sin_family=AF_INET;
ser_add.sin_addr.s_addr=htonl(INADDR_ANY);//设置为网络传输格式,因为是要传输给客户端
ser_add.sin_port=htons(SER_PORT);//设置网络传输格式,因为要传输给客户端;
printf("init ser_add success, IP is:%d\t,port is %d\n",ser_add.sin_addr.s_addr,ser_add.sin_port);
int ret =bind(listenfd,(struct sockaddr*)&ser_add,sizeof(ser_add));//设置监听;
if(ret<0){
perror("listen fail");
exit(1);
}
printf("bind success\n");
ret = listen(listenfd,20);//设置监听:
if(ret<0){
perror("listen fail");
exit(1);
}
printf("listen success\n");
printf("Waiting connections...\n");
int k=0;
while(1){
cli_add_len = sizeof(cli_add);
int connfd = accept(listenfd,(struct sockaddr*)&cli_add,&cli_add_len);//开始建立连接;
if(connfd<0){
perror("connect fail");
exit(1);
}
else{
k++;
printf("创建第 %d 个子进程\n",k);
pid = fork();
if(pid<0){
perror("fork fail\n");
exit(1);
}
else if(pid == 0){//进入子进程
close(listenfd);
while(1){
int len = read(connfd,buf,sizeof(buf));
if(len<0){
perror("read fail");
exit(1);
}
else if(len==0){
printf("客户端断开连接\n");
break;
}
else{
char str[256];
printf("客户端的IP:%s\t,端口:%d\n",inet_ntop(AF_INET,&cli_add.sin_addr,str,sizeof(str)),ntohs(cli_add.sin_port));
int len_w=write(STDOUT_FILENO,buf,len);//把从客户端读到的内容打印到屏幕;
if(len_w<0){
perror("write fail");
exit(1);
}
}
}
close(connfd);
return 0;//此时会发出一个SIGCHLD信号
}
else{//进入父进程:
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = do_sigchld;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD,&act,NULL);
//将SIGCHLD解除屏蔽:
sigprocmask(SIG_UNBLOCK,&myset,NULL);
close(connfd);
}
}
}
return 0;
}
/*************************************************************************
> File Name: client.c
> Author: xuchen_allen
> Mail: [email protected]
> Created Time: 2019年02月10日 星期日 21时02分17秒
************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#define _SEVER_IP_ "192.168.1.108"
#define _PORT_ 8080
int main()
{
int sfd,len;
struct sockaddr_in serv_addr;
char buf[1024];
sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd<0){
perror("socket fail");
exit(1);
}
else{
printf("client socket success\n");
}
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET,_SEVER_IP_,&serv_addr.sin_addr.s_addr);
serv_addr.sin_port = htons(_PORT_);
if(connect(sfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0){
perror("client conect fail");
exit(1);
}
else{
printf("client connect success\n");
}
while(1){
fgets(buf,sizeof(buf),stdin);
int r = write(sfd,buf,strlen(buf));
if(r<0){
perror("client write fail");
exit(1);
}
printf("write=============== %d\n",r);
}
close(sfd);
return 0;
}
顺便复习一下信号~~