这里我们需要简单实现网络版的计算器,我打算让它具有计算加法,减法,乘法,除法,还有取模 的功能。
例如(加法),我们需要实现一个服务器版的加法器,我们需要客户端把要计算的两个加数发过去,然后由服务端进行计算,最后把计算结果返回给客户端。
按照这个思路,客户端每次应该发送两个加数和一个操作符,如果要把这些数据分三次发送或者两次发送,在一个服务端对应多个客户端的时候,数据就会混乱,便于避免,我们应该一次发送这些数据。一种方法,可以把数据和操作符整体看做一个字符串发送过去,然后服务端接收到后按照它们的约定正确的解析出数据和操作数(分割),进行计算,再把结果返回给客户端。再一种方法,我们可以定义一个结构体来表示每次要交互的信息,直接给服务端发送结构体,然后服务端按照它们的约定对数据进行计算,再把结果返回给客户端,这里要想想,如果你进行了除0,模0,或者操作符非法的计算,那么计算的结果还有意义吗?所以可以定义一个状态数,比如规定,状态码为0则代表此次计算有意义,其余状态码值对应此次具体非法的操作,这里状态码也要返回给客户端。
下面就直接上代码啦,这里采用的是结构体的方法:
//Counter.hpp
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
using namespace std;
typedef struct Reques
{
int x;
int y;
char op;//caizoufu
}Reques;
typedef struct Respons
{
int status;
int result;
}Respons;
服务端:Server.cc
#include"Counter.hpp"
int main()
{
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
cerr<<"socket fail..."<<endl;
exit(1);
}
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_addr.s_addr=htonl(INADDR_ANY);
local.sin_port=htons(8080);
int ret1=bind(sock,(struct sockaddr *)&local,sizeof(local));
if(ret1<0)
{
cerr<<"bind fail..."<<endl;
exit(2);
}
int ret2=listen(sock,6);
if(ret2<0)
{
cerr<<"listen fail..."<<endl;
exit(3);
}
struct sockaddr_in peer;
while(1)
{
socklen_t len=sizeof(peer);
int onesock=accept(sock,(struct sockaddr *)&peer,&len);
if(onesock<0)
{
cerr<<"accept fail..."<<endl;
continue;
}
cout<<"Get a new line..."<<endl;
while(1)
{
Reques q;
int ret3=recv(onesock,(void *)&q,sizeof(q),0);
if(ret3==0)
{
cerr<<"Client close..."<<endl;
exit(4);
}
if(ret3<0)
{
cerr<<"revc fail..."<<endl;
exit(5);
}
Respons p={0,0};
switch(q.op)
{
case '+':p.result=q.x+q.y;
break;
case '-':p.result=q.x-q.y;
break;
case '*':p.result=q.x*q.y;
break;
case '/':if(q.y==0)
p.status=1;
else
p.result=q.x/q.y;
break;
case '%':if(q.y==0)
p.status=2;
else
p.result=q.x%q.y;
break;
default:p.status=3;
break;
}
send(onesock,(void *)&p,sizeof(p),0);
}
close(onesock);
}
return 0;
}
客户端:Client.cc
#include"Counter.hpp"
int main()
{
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
cerr<<"socket fail..."<<endl;
exit(1);
}
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port=htons(8080);
local.sin_addr.s_addr=inet_addr("127.0.0.1");
while(1)
{
socklen_t len=sizeof(local);
int ret1=connect(sock,(struct sockaddr *)&local,len);
if(ret1<0)
{
cerr<<"connect fail..."<<endl;
exit(2);
}
while(1)
{
Reques q;
cout<<"please into op: (q--quit) ";
cin>>q.op;
if(q.op=='q')
break;
cout<<"please into two inter: ";
cin>>q.x>>q.y;
int ret2=send(sock,(void *)&q,sizeof(q),0);
if(ret2<0)
{
cerr<<"send fail..."<<endl;
exit(3);
}
Respons p;
int ret3=recv(sock,(void *)&p,sizeof(p),0);
if(ret3<0)
{
cerr<<"recv fail..."<<endl;
exit(4);
}
cout<<"status:"<<p.status<<endl;
cout<<"result:"<<p.result<<endl;
}
close(sock);
}
return 0;
}
运行情况:(Linux)左边是服务端运行,右边是客户端运行呐
若有错误,欢迎指正:)