socket 实现简单的的计算器
服务端 server.c 对客户端的请求进行处理,并返回结果
客户端 client.c 向服务端发送一个表达式 如 add 1 2 表示 1+2 服务器返回结果;
主要功能 + - * / echo
代码:server.c
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<unistd.h> #include<sys/un.h> #include<sys/socket.h> #include<sys/wait.h> #include<sys/types.h> #include<netdb.h> #include<signal.h> #include<ctype.h> #define PORT 5000 //获取子进程退出信号 在退出时给出提示信息 void sig_handler(int signo) { pid_t pid; int stat; pid = waitpid(-1,&stat,WNOHANG); while(pid>0){ printf("child process terminated (PID: %ld)\n",(long)getpid()); pid = waitpid(-1,&stat,WNOHANG); } return; } typedef struct{ double a; double b; char s[10]; char echo_buf[1024]; }Mes; int main(int argc ,char *argv[]) { socklen_t clt_addr_len; int listen_fd; int com_fd; int i; static char send_buf[1024]; int len; int port; pid_t pid; struct sockaddr_in clt_addr; struct sockaddr_in srv_addr; if(argc!=1) { printf("Usage: %s port\n",argv[0]); exit(1); } if(signal(SIGCHLD,sig_handler) < 0){ perror("can not set the signal\n"); exit(1); } listen_fd = socket(PF_INET,SOCK_STREAM,0); if(listen_fd < 0){ perror("can not create listening socket\n"); exit(1); } memset(&srv_addr,0,sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(PORT); int t=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr)); if(t==-1){ perror("can not bind server socket\n"); exit(1); } t=listen(listen_fd,20); if(t==-1){ perror("can not listen the client connect request\n"); close(listen_fd); } memset(send_buf,0,1024); while(1) { len = sizeof(clt_addr); com_fd = accept(listen_fd,(struct sockaddr*)&clt_addr,&len); if(com_fd < 0){ if(errno == EINTR){ continue; } else{ perror("can not accept client connect request\n"); close(listen_fd); exit(1); } } pid = fork(); if(pid < 0){ perror("can not create the child process\n "); close(listen_fd); exit(1); }else if(pid == 0){ Mes mes; int n=sizeof(mes); while((len = read(com_fd,&mes,n))>0){ if(strcmp(mes.s,"echo")!=0){ printf("Message from client(%d):%s %.2lf %.2lf\n",len,mes.s,mes.a,mes.b); if(send_buf[0]=='@'){ break; } double result = 0; if(strcmp(mes.s,"add")==0){ printf("加法\n"); result = mes.a+mes.b; }else if(strcmp(mes.s,"sub")==0){ printf("减法\n"); result = mes.a - mes.b; }else if(strcmp(mes.s,"mul")==0){ printf("乘法\n"); result = mes.a * mes.b; }else if(strcmp(mes.s,"div")==0){ printf("除法\n"); if(mes.b == 0){ printf("除数为0\n "); result == 0; }else{ result = mes.a / mes.b; } }else{ printf("不识别的操作\n"); } printf("结果:result = %.2lf\n",result); if(mes.b == 0 && (strcmp(mes.s,"div") == 0)){ sprintf(send_buf,"%s","除数为0 无意义\n"); }else{ sprintf(send_buf,"%.2lf",result); } }else{ printf("客户端的消息:%s\n",mes.echo_buf); printf("回复的消息"); fgets(send_buf,1024,stdin); } write(com_fd,send_buf,strlen(send_buf)); } close(com_fd); return 0; }else{ close(com_fd); } } return 0; }
client.c:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/un.h> #include<unistd.h> #include<netdb.h> #include<errno.h> #include<arpa/inet.h> #define PORT 5000 typedef struct{ double a; double b; char s[10]; char echo_buf[1024]; }Mes; int main(int argc,char *argv[]) { int connect_fd; int ret; char recv_buf[1024]; int i; int port; int len; static struct sockaddr_in srv_addr; if(argc!=1){ printf("Usage: %s server_ip_address port \n",argv[0]); exit(1); } connect_fd = socket(PF_INET,SOCK_STREAM,0); if(connect_fd < 0){ perror("can not create communication socket\n"); exit(1); } memset(&srv_addr,0,sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(PORT); if((connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr)))==-1){ perror("can not to the server\n"); close(connect_fd); exit(1); } memset(recv_buf,0,1024); while(1){ Mes mes; int n=sizeof(mes); printf("请输入表达式:\n"); scanf("%s",mes.s); if(strcmp(mes.s,"echo")==0){ fgets(mes.echo_buf,1024,stdin); mes.a = 0; mes.b = 0; }else{ scanf("%lf%lf",&mes.a,&mes.b); sprintf(mes.echo_buf,"%s","NULL"); } write(connect_fd,&mes,n); len = read(connect_fd,recv_buf,n); if(strcmp(mes.s,"echo")==0){ printf("服务端回复的消息:%s\n",recv_buf); }else if(len > 0){ double result; sscanf(recv_buf,"%lf",&result); printf("计算的结果: %.2lf\n",result); if(recv_buf[0] == '@') break; } } close(connect_fd); return 0; }
运行结果截图:
server:
client: