多进程版本
服务器
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <string>
void mywait(int num)
{while(1){pid_t pid=waitpid(-1,NULL,WNOHANG);//非阻塞回收进程if(pid>0)printf("回收了%d\n",pid);if(pid==0||pid==-1)break;}
}
int main()
{int flag=0;struct sockaddr_in saddr;saddr.sin_port = htons(8999);saddr.sin_addr.s_addr = INADDR_ANY;saddr.sin_family = AF_INET;int sfd = socket(AF_INET, SOCK_STREAM, 0);struct sigaction sig;sigemptyset(&sig.sa_mask);sig.sa_flags=0;sig.sa_handler=mywait;sigaction(SIGCHLD,&sig,NULL);//设置SIGCHLD信号捕捉if (sfd == -1){perror("socket error");return 1;}flag = bind(sfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));if (flag == -1){perror("bind error");return 1;}flag=listen(sfd, 100);if(flag==-1){perror("listen error");return 1;}struct sockaddr_in caddr;int clen=sizeof(caddr);while (1){int cfd = accept(sfd, (struct sockaddr*)&caddr, (socklen_t*)&clen);if (cfd == -1){perror("accept error");continue;}char ip[1024]={'\0'};//必须加上,不然解析IP会失败printf("接收到了客户端%s:%d的连接\n",inet_ntop(AF_INET,&caddr.sin_addr,ip,1024),ntohs(caddr.sin_port));int pid=fork();if(pid==0){close(sfd);while(1){char buf[1024] = {'\0'};flag = recv(cfd, buf, 1024, 0);if (flag==-1){perror("read error");break;}else if(flag==0){printf("连接断开\n");break;}printf("从客户端收到数据:%s\n", buf);std::string sendstr="服务器收到了"+std::to_string(caddr.sin_port)+"的数据";flag = send(cfd, sendstr.c_str(), sendstr.length(), 0);if (flag == -1){perror("send error");break;}memset(buf, 0, 1024);}exit(0);}else{close(cfd);}}return 0;
}
客户端
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string>
int main()
{int flag;struct sockaddr_in* caddr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));inet_pton(AF_INET, "192.168.101.231", &caddr->sin_addr.s_addr);caddr->sin_family = AF_INET;caddr->sin_port = htons(8999);int cfd = socket(AF_INET, SOCK_STREAM, 0);if (cfd == -1){perror("socket error");return 1;}flag= connect(cfd, (struct sockaddr*)caddr, sizeof(struct sockaddr));//caddr就是指针类型if (flag == -1){perror("connect error");return 1;}int i=0;while (1){char buf[1024] = {'\0'};std::string sendstr="我是客户端,我发送了"+std::to_string(i);flag = send(cfd, sendstr.c_str(), sendstr.length(),0);if (flag == -1){perror("send error");continue;}printf("send:%s\n", sendstr.c_str());flag = recv(cfd, buf, 1024, 0);if (flag == -1){perror("recv error");continue;}printf("客户端收到数据:%s\n", buf);memset(buf, 0, 1024);i++;sleep(1);}close(cfd);return 0;
}
多线程版本服务器
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string>
#include <pthread.h>
void* handle(void* arg)
{int flag=0;int* arr=(int*)arg;int cfd=arr[0];int port=arr[1];while(1){char buf[1024] = {'\0'};flag = recv(cfd, buf, 1024, 0);if (flag==-1){perror("read error");break;}else if(flag==0){printf("连接断开\n");break;}printf("从客户端%d收到数据:%s\n",port,buf);std::string sendstr="服务器收到了"+std::to_string(port)+"的数据";flag = send(cfd, sendstr.c_str(), sendstr.length(), 0);if (flag == -1){perror("send error");break;}memset(buf, 0, 1024);}close(cfd);return NULL;
}
int main()
{int flag=0;struct sockaddr_in saddr;saddr.sin_port = htons(8999);saddr.sin_addr.s_addr = INADDR_ANY;saddr.sin_family = AF_INET;int sfd = socket(AF_INET, SOCK_STREAM, 0);if (sfd == -1){perror("socket error");return 1;}flag = bind(sfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));if (flag == -1){perror("bind error");return 1;}flag=listen(sfd, 100);if(flag==-1){perror("listen error");return 1;}while (1){struct sockaddr_in caddr;int clen=sizeof(caddr);int cfd = accept(sfd, (struct sockaddr*)&caddr, (socklen_t*)&clen);int port=ntohs(caddr.sin_port);printf("端口号:%d\n",port);if (cfd == -1){perror("accept error");continue;}char ip[1024]={'\0'};//必须加上,不然解析IP会失败printf("接收到了客户端%s:%d的连接\n",inet_ntop(AF_INET,&caddr.sin_addr,ip,1024),port);pthread_t tid;int arg[2]={cfd,port};pthread_create(&tid,NULL,handle,(void*)arg);//这里不能传递cfd的地址,各个线程是共享这个地址的pthread_detach(tid);}return 0;
}
运行效果: