5.2 计算器服务器端/客户端示例

来源:互联网 发布:js 多图上传插件 编辑:程序博客网 时间:2024/06/14 06:54

通信过程中一般都需要提前定义好通信协议,TCP中亦是如此。

我们编写计算器的例子,定义好应用层协议:

    1.客户端连接到服务器端后以1字节整数形式传递待算数字个数;

    2.客户端向服务器端传递的每个整数型数据占用4字节;

    3.传递完数据后,接着1个字节运算符;

    4.选择字符+,-,*,/;

    5.服务器以4字节整数型向客户端传回运算结果;

    6.客户端得到运算结果后终止与服务器端的连接。


Server端代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE 1024#define OPSZ4void error_handling(char *message);int calculate(int opnum,int opnds[],char oprator);int main(int argc, char *argv[]){int serv_sock;int clnt_sock;char opinfo[BUF_SIZE];int result,opnd_cnt,i;int recv_cnt,recv_len;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_sz;if(argc != 2){printf("Usage : %s <port>\n",argv[0]);exit(1);}serv_sock = socket(PF_INET,SOCK_STREAM,0);if(serv_sock == -1){error_handling("socket() error");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);serv_addr.sin_port=htons(atoi(argv[1]));if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) == -1){error_handling("bind() error");}if(listen(serv_sock,5) == -1){error_handling("listen() error");}clnt_addr_sz = sizeof(clnt_addr);for(i=0;i<5;i++){opnd_cnt = 0;clnt_sock = accept(serv_sock,(struct sockaddr *)&clnt_addr,&clnt_addr_sz);read(clnt_sock,&opnd_cnt,1);recv_len = 0;while((opnd_cnt*OPSZ+1)>recv_len){recv_cnt = read(clnt_sock,&opinfo[recv_len],BUF_SIZE-1);recv_len += recv_cnt;}result = calculate(opnd_cnt,(int *)opinfo,opinfo[recv_len-1]);write(clnt_sock,(char *)&result,sizeof(result));close(clnt_sock);}close(serv_sock);return 0;}int calculate(int opnum,int opnds[],char op){int result = opnds[0],i;switch(op){case '+':for(i=1;i<opnum;i++) result +=opnds[i];break;case '-':for(i=1;i<opnum;i++) result -= opnds[i];break;case '*':for(i=1;i<opnum;i++) result *= opnds[i];break;}return result;}void error_handling(char *message){fputs(message,stderr);fputs("\n",stderr);exit(1);}


Client端代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE1024#define RLT_SIZE4#define OPSZ4void error_handling(char *message);int main(int argc,char *argv[]){int sock;char opmsg[BUF_SIZE];int result,opnd_cnt,i;struct sockaddr_in serv_addr;if(argc != 3){printf("Usage : %s <IP> <port>\n",argv[0]);exit(1);}sock = socket(PF_INET,SOCK_STREAM,0);if(sock == -1){error_handling("socket() error");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));if(connect(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1){error_handling("connect() error\r\n");}else{printf("Connected....");}fputs("Operand count: ",stdout);scanf("%d",&opnd_cnt);opmsg[0] = (char)opnd_cnt;for(i=0;i<opnd_cnt;i++){printf("Operand %d: ",i+1);scanf("%d",(int *)&opmsg[i*OPSZ+1]);}fgetc(stdin);//end charfputs("Operator: ",stdout);scanf("%c",&opmsg[opnd_cnt*OPSZ+1]);write(sock,opmsg,opnd_cnt*OPSZ+2);read(sock,&result,RLT_SIZE);printf("Operation result:%d \n",result);close(sock);return 0;}void error_handling(char *message){fputs(message,stderr);fputs("\n",stderr);exit(1);}


Server端执行结果:

alex@alex-VirtualBox:~/Share/Test/tcpip$ ./op_server 9190


Client执行结果:

alex@alex-VirtualBox:~/Share/Test/tcpip$ ./op_client 127.0.0.1 9190Connected....Operand count: 3Operand 1: 123Operand 2: 123Operand 3: 234Operator: +Operation result:480

应用层可以定义好对应的结构体,会更加直观。



0 0
原创粉丝点击