博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20155216 2017-2018-1 第八周课下作业2
阅读量:4681 次
发布时间:2019-06-09

本文共 9364 字,大约阅读时间需要 31 分钟。

20155216 2017-2018-1 第八周课下作业2

作业内容:

把daytime服务器分别用多进程和多线程实现成并发服务器并测试。

多进程实现daytime服务器

服务器端源代码:

#include 
// for sockaddr_in#include
// for socket#include
// for socket#include
// for printf#include
// for exit#include
// for bzero#include
// for fork#include
// for signal#include
// for wait#include
#include
#define HELLO_WORLD_SERVER_PORT 6666 #define LENGTH_OF_LISTEN_QUEUE 20#define BUFFER_SIZE 1024void reaper(int sig){ int status; //调用wait3读取子进程的返回值,使zombie状态的子进程彻底释放 while(wait3(&status,WNOHANG,(struct rusage*)0) >=0) ;}int main(int argc, char **argv){ //设置一个socket地址结构server_addr,代表服务器internet地址, 端口 struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT); time_t t; //创建用于internet的流协议(TCP)socket,用server_socket代表服务器socket int server_socket = socket(AF_INET,SOCK_STREAM,0); if( server_socket < 0) { printf("Create Socket Failed!\n"); exit(1); } //把socket和socket地址结构联系起来 if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) { printf("Server Bind Port : %d Failed!\n", HELLO_WORLD_SERVER_PORT); exit(1); } //server_socket用于监听 if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) ) { printf("Server Listen Failed!"); exit(1); } //通知操作系统,当收到子进程的退出信号(SIGCHLD)时,执行reaper函数,释放zombie状态的进程 (void)signal(SIGCHLD,reaper); while (1) //服务器端要一直运行 { //定义客户端的socket地址结构client_addr struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); //接受一个到server_socket代表的socket的一个连接 //如果没有连接请求,就等待到有连接请求--这是accept函数的特性 //accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户的通信 //new_server_socket代表了服务器和客户端之间的一个通信通道 //accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中 int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length); if ( new_server_socket < 0) { printf("Server Accept Failed!\n"); break; } int child_process_pid = fork(); //fork()后,子进程是主进程的拷贝 //在主进程和子进程中的区别是fork()的返回值不同. if(child_process_pid == 0 )//如果当前进程是子进程,就执行与客户端的交互 { t=time(NULL); close(server_socket); //子进程中不需要被复制过来的server_socket char buffer[BUFFER_SIZE]; bzero(buffer, BUFFER_SIZE); //strcpy(buffer,"20155216实现"); strcat(buffer,"\n"); //C语言字符串连接 //发送buffer中的字符串到new_server_socket,实际是给客户端 send(new_server_socket,buffer,BUFFER_SIZE,0); printf("服务器实现者学号:20155216\n"); printf("客户端IP:%s \n",inet_ntoa(client.sin_addr)); printf("当前时间: %s\n",ctime(&t)); send(new_server_socket,(void *)&t,sizeof(time_t),0); bzero(buffer,BUFFER_SIZE); //接收客户端发送来的信息到buffer中 length = recv(new_server_socket,buffer,BUFFER_SIZE,0); if (length < 0) { printf("Server Recieve Data Failed!\n"); exit(1); } printf("\n%s\n",buffer); //关闭与客户端的连接 close(new_server_socket); exit(0); } else if(child_process_pid > 0) //如果当前进程是主进程 close(new_server_socket); //主进程中不需要用于同客户端交互的new_server_socket } //关闭监听用的socket close(server_socket); return 0;}

客户端源代码:

#include 
// for sockaddr_in#include
// for socket#include
// for socket#include
// for printf#include
// for exit#include
// for bzero#include
#define HELLO_WORLD_SERVER_PORT 6666 #define BUFFER_SIZE 1024void talk_to_server(char ** argv){ //设置一个socket地址结构client_addr,代表客户机internet地址, 端口 struct sockaddr_in client_addr; bzero(&client_addr,sizeof(client_addr)); //把一段内存区的内容全部设置为0 client_addr.sin_family = AF_INET; //internet协议族 client_addr.sin_addr.s_addr = htons(INADDR_ANY);//INADDR_ANY表示自动获取本机地址 client_addr.sin_port = htons(0); //0表示让系统自动分配一个空闲端口 //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket int client_socket = socket(AF_INET,SOCK_STREAM,0); time_t t; if( client_socket < 0) { printf("Create Socket Failed!\n"); exit(1); } //把客户机的socket和客户机的socket地址结构联系起来 if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))) { printf("Client Bind Port Failed!\n"); exit(1); } //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口 struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; if(inet_aton(argv[1],&server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数 { printf("Server IP Address Error!\n"); exit(1); } server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT); socklen_t server_addr_length = sizeof(server_addr); //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接 if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0) { printf("Can Not Connect To %s!\n",argv[1]); exit(1); } char buffer[BUFFER_SIZE]; bzero(buffer,BUFFER_SIZE); //从服务器接收数据到buffer中 int length = recv(client_socket,buffer,BUFFER_SIZE,0); if(length < 0) { printf("Recieve Data From Server %s Failed!\n", argv[1]); exit(1); } printf("From Server %s :\t%s\n",argv[1],buffer); length = recv(client_socket,(void *)&t,sizeof(time_t),0); if(length < 0) { printf("Recieve Data From Server %s Failed!\n", argv[1]); exit(1); } printf("当前时间: %s \n",ctime(&t)); bzero(buffer,BUFFER_SIZE); //strcpy(buffer,"Thanks!"); //向服务器发送buffer中的数据 send(client_socket,buffer,BUFFER_SIZE,0); //关闭socket close(client_socket);}int main(int argc, char **argv){ if (argc != 2) { printf("Usage: .\%s ServerIPAddress\n",argv[0]); exit(1); } talk_to_server(argv); return 0;}

实现结果:

1071483-20171111190413263-1518034256.png

可实现并发,即多个客户端同时访问服务器,并给出不同的系统时间。

多线程实现daytime服务器

服务器源代码:

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 1234#define BACKLOG 2#define MAXDATASIZE 1000void process_cli(int connectfd,struct sockaddr_in client);void sig_handler(int s);int main(){ int opt,listenfd,connectfd; pid_t pid; struct sockaddr_in server; struct sockaddr_in client; int sin_size; struct sigaction act; struct sigaction oact; act.sa_handler=sig_handler; sigemptyset(&act.sa_mask); act.sa_flags=0; printf("服务器实现者学号:20155216\n"); if(sigaction(SIGCHLD,&act,&oact)<0) { perror("Sigaction failed!\n"); exit(1); } if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("Creating socket failed.\n"); exit(1); } opt=SO_REUSEADDR; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1) { perror("Bind error.\n"); exit(1); } if(listen(listenfd,BACKLOG)==-1) { perror("listen() error.\n"); exit(1); } sin_size=sizeof(struct sockaddr_in); while(1) { if((connectfd=accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) { if(errno==EINTR) continue; perror("accept() error.\n"); exit(1); } if((pid=fork())>0) { close(connectfd); continue; } else if(pid==0) { close(listenfd); process_cli(connectfd,client); exit(0); } else { printf("fork error.\n"); exit(1); } } close(listenfd); return 0;}void process_cli(int connectfd,struct sockaddr_in client){ int i,num; char recvbuf[MAXDATASIZE]; char sendbuf[MAXDATASIZE]; char cli_name[MAXDATASIZE]; time_t t; t=time(NULL); printf("客户端IP:%s \n",inet_ntoa(client.sin_addr)); num=recv(connectfd,cli_name,MAXDATASIZE,0); if(num==0) { close(connectfd); printf("Client disconnected.\n"); return; } send(connectfd,(void *)&t,sizeof(time_t),0); while(num=recv(connectfd,recvbuf,MAXDATASIZE,0)) { recvbuf[num]='\0'; printf("当前时间:%s\n",ctime(&t)); //send(connectfd,(void *)&t,sizeof(time_t),0); } close(connectfd);}void sig_handler(int s){ pid_t pid; int stat; while((pid=waitpid(-1,&stat,WNOHANG))>0) printf("子进程 %d 关闭。\n",pid); return;}

客户端源代码:

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 1234#define MAXDATASIZE 1000void process(FILE *fp,int sockfd);char *getMessage(char *sendline,int len,FILE *fp);int main(int argc,char *argv[]){ int fd; struct hostent *he; struct sockaddr_in server; if(argc!=2) { printf("Usage: %s
\n",argv[0]); exit(1); } if((he=gethostbyname(argv[1]))==NULL) { printf("gethostbyname error.\n"); exit(1); } if((fd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socket() error.\n"); exit(1); } bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr=*((struct in_addr *)he->h_addr); if(connect(fd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1) { perror("connect() error.\n"); exit(1); } process(stdin,fd); close(fd); return 0;}void process(FILE *fp,int sockfd){ char sendbuf[MAXDATASIZE]; char recvbuf[MAXDATASIZE]; int num; time_t t; t=time(NULL); printf("用户名:\n"); if(fgets(sendbuf,MAXDATASIZE,fp)==NULL) { printf("lease enter your name,now you have exit.\n"); return; } send(sockfd,sendbuf,strlen(sendbuf),0); while(getMessage(sendbuf,MAXDATASIZE,fp)!=NULL) { send(sockfd,sendbuf,strlen(sendbuf),0); if((num=recv(sockfd,recvbuf,MAXDATASIZE,0))==0) { printf("Server no send you any data.\n"); return; } recvbuf[num]='\0'; printf("服务器消息:%s\n",ctime(&t)); } printf("Exit.\n");}char *getMessage(char *sendline,int len,FILE *fp){ printf("请输入请求:\n"); return(fgets(sendline,len,fp));}

运行结果:

1071483-20171111191135466-2034758549.png

可实现并发,即多个客户端同时访问服务器,并给出不同的系统时间。

转载于:https://www.cnblogs.com/LeeX1997/p/7819752.html

你可能感兴趣的文章
一种人吃蜂蜜火上浇油
查看>>
让TP5.0在SWOOLE上飞起来
查看>>
Mysql - ORDER BY详解
查看>>
百度云高速下载Pandownload
查看>>
python 基础 three day
查看>>
Redis
查看>>
Bat 批处理之 for/f 详解
查看>>
Python之os模块介绍
查看>>
SQLServer查询所有子节点
查看>>
Javascript 兼容 IE6、IE7、FF 的“加入收藏”“设为首页”
查看>>
(转)EOS中账户、钱包和密钥的关系
查看>>
在C#中,如何将一个int转换成一个byte array,又如何将一个byte array转换成一个int...
查看>>
DOM和BOM
查看>>
web前端_跨域问题方法总结
查看>>
英文词频统计预备,组合数据类型练习
查看>>
C# Windows - ListBox&CheckedListBox
查看>>
AES对上传文件解密并加密的实现(JAVA实现)
查看>>
ThreadLocal 正名
查看>>
AngularJS自定义指令详解(有分页插件代码)
查看>>
数据挖掘学习--数据仓库
查看>>