服务器端采用简单的socket编程制作,多个客户端同时连接采用fork分离进程,当客户端退出时,采用sigcation函数来销毁子进程,防止僵尸进程的产生。
服务器端代码如下:
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wait.h>
#include <signal.h>
using namespace std;
void read_childproc(int sig);
int main(int argc,char *argv[])
{
int listenfd,connfd;
sockaddr_in servaddr,cliaddr;
char buf[4096];
int recvNum;
int addrLen=sizeof(servaddr);
pid_t pid;
struct sigaction act;
if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf("socket error:%s:%d\n",strerror(errno),errno);
exit(1);
}
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
int state=sigaction(SIGCHLD,&act,0);
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
if((bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)))==-1)
{
printf("bind error:%s:%d\n",strerror(errno),errno);
exit(1);
}
if((listen(listenfd,10))==-1)
{
printf("listen error:%s:%d\n",strerror(errno),errno);
exit(1);
}
printf("=========waiting client's connection===========\n");
while(1)
{
if((connfd=accept(listenfd,(struct sockaddr*)&cliaddr,(socklen_t *)&addrLen))==-1)
{
printf("connect error:%s:%d\n",strerror(errno),errno);
exit(1);
}
else
{
printf("client id:%d\n",connfd);
}
pid=fork();
if(pid==-1)
{
close(connfd);
continue;
}
if(pid==0) /*子进程运行区域*/
{
close(listenfd);
while((recvNum=read(connfd,buf,1024))!=0)
{
write(connfd,buf,recvNum);
std::cout<<buf<<pid<<std::endl;
}
close(connfd);
}
else
{
close(connfd);
}
}
close(listenfd);
return 0;
}
void read_childproc(int sig)
{
pid_t pid;
int status;
pid=waitpid(-1,&status,WNOHANG);
printf("removed proc id:%d\n",pid);
}
客户端代码:
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wait.h>
#include <signal.h>
void read_childproc(int sig);
int main(int argc,char *argv[])
{
int connfd,state;
sockaddr_in servaddr;
struct sigaction act;
char buf[4096];
char msg[1024];
int writeNum;
if((connfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf("socket error:%s:%d",strerror(errno),errno);
exit(1);
}
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
state=sigaction(SIGINT,&act,0);
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
if((connect(connfd,(struct sockaddr*)&servaddr,sizeof(servaddr)))==-1)
{
printf("connect error:%s:%d",strerror(errno),errno);
exit(1);
}
while(1)
{
fgets(msg,1024,stdin);
if( (!strcmp(msg,"q\n")) ||(!strcmp(msg,"Q\n")))
{
shutdown(connfd,SHUT_WR);
return 1;
}
writeNum=write(connfd,msg,sizeof(msg));
read(connfd,buf,4096);
buf[writeNum]=0;
printf("send msg:%s",buf);
}
close(connfd);
return 0;
}
void read_childproc(int sig)
{
pid_t pid;
int status;
pid=waitpid(-1,&status,WNOHANG);
printf("removed proc id:%d\n",pid);
}