服务器端
#define _XOPEN_SOURCE
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>
void recycleChild(int arg){
while(1){
int ret=waitpid(-1,NULL,WNOHANG);
if(ret==-1){
//所有的子进程都回收了
break;
}else if(ret==0){
//还有子进程活着
break;
}else if(ret>0){
//被回收了
printf("子进程 %d 被回收了\n",ret);
}
}
}
//多进程实现并发服务器
int main()
{
struct sigaction act;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
act.sa_handler=recycleChild;
//注册信号捕捉
sigaction(SIGCHLD,&act,NULL);
//创建套接字
int lfd=socket(AF_INET,SOCK_STREAM,0);
if(lfd==-1){
perror("socket");
exit(-1);
}
//绑定IP和端口
struct sockaddr_in saddr;
saddr.sin_family=AF_INET;
saddr.sin_addr.s_addr=INADDR_ANY;
saddr.sin_port=htons(9999);
int ret=bind(lfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret==-1){
perror("bind");
exit(-1);
}
//设置监听事件
ret=listen(lfd,5);
if(ret==-1){
perror("listen");
exit(-1);
}
//不断循环等待客户端连接
while(1){
//接收连接
struct sockaddr_in caddr;
socklen_t len=sizeof(caddr);
int cfd=accept(lfd,(struct sockaddr*)& caddr,&len);
if(cfd==-1){
if(errno==EINTR) //处理由于接收到一个信号导致accept函数被中断的情况
continue;
perror("accept");
exit(-1);
}
//通信,子进程负责
pid_t pid=fork();
if(pid==0){
//获取客户端的信息
char clientIP[16];
inet_ntop(AF_INET,&caddr.sin_addr.s_addr,clientIP,sizeof(clientIP));
unsigned short clientPort=ntohs(caddr.sin_port);
printf("client ip is : %s, port is %d\n",clientIP,clientPort);
//循环通信
while(1){
//接收客户端发来的数据
char recvBuf[1024];
ret=read(cfd,recvBuf,sizeof(recvBuf));
if(ret==-1){
perror("read");
exit(-1);
}
else if(ret>0){
printf("recv client data: %s\n",recvBuf);
}
else if(ret==0){
//客户端断开连接
printf("client closed");
break;
}
//发送数据
write(cfd,recvBuf,strlen(recvBuf));
}
close(cfd);
exit(0); //退出当前子进程
}
}
//关闭连接
close(lfd);
return 0;
}
客户端
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(){
//1.创建socket套接字
int fd=socket(AF_INET,SOCK_STREAM,0);
if(fd==-1){
perror("socket");
exit(-1);
}
//2.连接服务器
struct sockaddr_in serveraddr;
serveraddr.sin_family=AF_INET;
inet_pton(AF_INET,"192.168.31.134",&serveraddr.sin_addr.s_addr);
serveraddr.sin_port=htons(9999);
int ret=connect(fd,(struct sockaddr*)& serveraddr,sizeof(serveraddr));
if(ret==-1){
perror("connect");
exit(-1);
}
//通信
char data[1024];
char recvBuf[1024];
int i=0;
while(1){
//3.发送数据
sprintf(data,"data : %d\n",i++);
write(fd,data,strlen(data));
//4.接收数据
int len=read(fd,recvBuf,sizeof(recvBuf));
if(len==-1){
perror("read");
exit(-1);
}
else if(len>0){
printf("recv server data: %s\n",recvBuf);
}
else if(len==0){
printf("server closed\n");
break;
}
//读写操作已经完成,此时结束客户端不会产生Connection reset by peer的错误,产生此错误的原因是客户端关闭了仍进行读写操作
sleep(1);
}
//5.关闭连接
close(fd);
return 0;
}