作业
1、多进程多线程并发服务器,再实现一遍(重点模型)
多进程并发服务器
多进程服务器 PIDserver.c 代码
#include <myhead.h>
#define SERPORT 7777
#define SERIP "192.168.19.128"
#define BACKLOG 10void hande(int sss)
{if(sss==SIGCHLD){while(waitpid(-1,NULL,WNOHANG)!=-1);}//回收僵尸进程
}int main(int argc, const char *argv[])
{if(signal(SIGCHLD,hande)==SIG_ERR)//捕获子进程退出的信号{perror("signal");return -1;}//1、创建原始套接字int oldfd = socket(AF_INET,SOCK_STREAM,0);if(oldfd ==-1){perror("socket");return -1;}//端口号快速复用int kkk=666;if(setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&kkk,sizeof(kkk))==-1){printf("setsockopt");return -1;}printf("端口快速复用成功\n");struct sockaddr_in sin = {.sin_family = AF_INET,.sin_port = htons(SERPORT),.sin_addr.s_addr = inet_addr(SERIP)};//2、绑定if(bind(oldfd,(struct sockaddr *)&sin,sizeof(sin))==-1){perror("bind");return -1;}//3、监听if(listen(oldfd,BACKLOG)==-1){perror("listen");return -1;}//创建子进程,父进程负责接收客户端请求,子进程负责数据收发struct sockaddr_in cin;int cinlen = sizeof(cin);while(1){int newfd = accept(oldfd,(struct sockaddr *)&cin,&cinlen);if(newfd==-1){perror("accept");return -1;}printf("newfd = %d\n",newfd);printf("%s:%d连接成功\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));pid_t pid = fork();//创建子进程if(pid>0)//父进程{//close(newfd);//关闭文件描述符}else if(pid==0)//子进程{close(oldfd);//关闭旧的文件描述符char buff[1024];while(1){int len = recv(newfd,buff,sizeof(buff),0);if(len==0){printf("客户端退出\n");break;}printf("服务器收到信息:%s\n",buff);strcat(buff,"^_^");send(newfd,buff,sizeof(buff),0);printf("发送成功\n");}//close(newfd);//关闭新的文件描述符exit(0);//退出子进程}else{perror("fork");return -1;}}close(oldfd);return 0;
}
多进程客户端 clinet.c 代码
#include <myhead.h>#define CLIPORT 7777
#define CLIIP "192.168.19.128"
int main(int argc, const char *argv[])
{int oldfd = socket(AF_INET,SOCK_STREAM,0);//1、创建原始套节字if(oldfd==-1){perror("socket");return -1;}//2、bind可选//3、连接服务器struct sockaddr_in cin = {.sin_family = AF_INET,//IPV4通信.sin_port = htons(CLIPORT),//端口号转为网络字节序.sin_addr.s_addr = inet_addr(CLIIP)//IP地址转为网络字节序};if(connect(oldfd,(struct sockaddr *)&cin,sizeof(cin))==-1){perror("connect");return -1;}printf("连接服务器成功\n");char buff[1024] = "";while(1)//4、收发消息{memset(buff,0,sizeof(buff));printf("客户端发信息:");fgets(buff,sizeof(buff),stdin);buff[strlen(buff)-1] = '\0';send(oldfd,buff,sizeof(buff),0);//阻塞发送recv(oldfd,buff,sizeof(buff),0);//阻塞接收printf("收到服务器的消息:%s\n",buff);}close(oldfd);return 0;
}
运行结果:
多线程并发服务器
多线程服务器
#include <myhead.h>
#define SERPORT 6666
#define SERIP "192.168.19.128"
#define BACKLOG 20
typedef struct
{int newfd;//存储新文件描述符struct sockaddr_in cin;//存储客户端信息
}HMY;void *fun1(void *sss)
{int newfd = ((HMY *)sss)->newfd;struct sockaddr_in cin = ((HMY *)sss)->cin;//解析客户端信息char buff[1024];while(1){bzero(buff,sizeof(buff));int len = recv(newfd,buff,sizeof(buff),0);printf("收到%s:%d的信息:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buff);//输出客户端信息if(len==0){printf("客户端退出\n");break;}strcat(buff,"hongmingyuan");//回个信息send(newfd,buff,sizeof(buff),0);printf("发送成功\n");}pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{int oldfd = socket(AF_INET,SOCK_STREAM,0);//1、创建套接字if(oldfd==-1){perror("socket");return -1;}int atao = 8;if(setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&atao,sizeof(atao))==-1){perror("setsockopt");return -1;}printf("端口号快速复用成功\n");struct sockaddr_in sin = {.sin_family =AF_INET,.sin_port = htons(SERPORT),.sin_addr.s_addr = inet_addr(SERIP)};if(bind(oldfd,(struct sockaddr *)&sin,sizeof(sin))==-1)//2、绑定{perror("bind");return -1;}if(listen(oldfd,BACKLOG)==-1)//3、监听成功{perror("listen");return -1;}printf("监听成功\n");struct sockaddr_in cin;int cinlen = sizeof(cin);HMY MSG;//定义子线程函数的参数while(1){//accept接收客户端请求int newfd = accept(oldfd,(struct sockaddr *)&cin,&cinlen);if(newfd==-1){perror("accept");return -1;}printf("%s:%d发来请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));MSG.newfd = newfd;MSG.cin = cin;//创建子线程与客户端通信pthread_t tid;if(pthread_create(&tid,NULL,fun1,&MSG)!=0){perror("pthread_create");return -1;}//回收子线程资源//pthread_join(tid,NULL);//不能使用join回收子线程资源pthread_detach(tid);//挂起由系统回收}//关闭旧的描述符close(oldfd);return 0;
}
多线程客户端
#include <myhead.h>#define CLIPORT 6666
#define CLIIP "192.168.19.128"
int main(int argc, const char *argv[])
{//1、创建原始套节字int oldfd = socket(AF_INET,SOCK_STREAM,0);if(oldfd==-1){perror("socket");return -1;}//2、bind可选//3、连接服务器struct sockaddr_in cin = {.sin_family = AF_INET,//IPV4通信.sin_port = htons(CLIPORT),//端口号转为网络字节序.sin_addr.s_addr = inet_addr(CLIIP)//IP地址转为网络字节序};if(connect(oldfd,(struct sockaddr *)&cin,sizeof(cin))==-1){perror("connect");return -1;}printf("连接服务器成功\n");char buff[1024] = "";while(1)//4、收发消息{memset(buff,0,sizeof(buff));printf("客户端发信息:");fgets(buff,sizeof(buff),stdin);buff[strlen(buff)-1] = '\0';send(oldfd,buff,sizeof(buff),0);//阻塞发送recv(oldfd,buff,sizeof(buff),0);//阻塞接收printf("收到服务器的消息:%s\n",buff);}close(oldfd);return 0;
}
运行结果:
2、广播发送接收端,自己实现一遍(重点模型)
广播发送接收端
发送端UDPsend.c代码
#include <myhead.h>
#define SENDPORT 6666
#define SENDIP "192.168.19.255"//广播IP地址int main(int argc, const char *argv[])
{//1、创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("socket");return -1;}//2、设置套接字允许广播int kkk=2;if(setsockopt(oldfd,SOL_SOCKET,SO_BROADCAST,&kkk,sizeof(kkk))==-1){perror("setsockopt");return -1;}printf("设置允许广播成功\n");struct sockaddr_in send = {.sin_family = AF_INET,.sin_port = htons(SENDPORT),.sin_addr.s_addr = inet_addr(SENDIP)};struct sockaddr_in ree;int reelen = sizeof(ree);char buff[1024];while(1)//3、发送信息{bzero(buff,sizeof(buff));sleep(2);strcat(buff,"5201314");sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&send,sizeof(send));printf("发送成功\n");}close(oldfd);//关闭套接字return 0;
}
接收端recv.c代码
#include <myhead.h>
#define SENDPORT 6666
#define SENDIP "192.168.19.255"//广播IP地址int main(int argc, const char *argv[])
{//1、创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("socket");return -1;}struct sockaddr_in ree = {.sin_family = AF_INET,.sin_port = htons(SENDPORT),.sin_addr.s_addr = inet_addr(SENDIP)};//2、绑定if(bind(oldfd,(struct sockaddr *)&ree,sizeof(ree))==-1){perror("bind");return -1;}//3、收发消息char buff[1024];while(1){bzero(buff,sizeof(buff));recvfrom(oldfd,buff,sizeof(buff),0,NULL,NULL);printf("%s\n",buff);strcat(buff,"^_^");sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&ree,sizeof(ree));printf("发送成功\n");}return 0;
}
运行结果: