基于TCP实现简单网络计算器

这里我们需要简单实现网络版的计算器,我打算让它具有计算加法,减法,乘法,除法,还有取模 的功能。

例如(加法),我们需要实现一个服务器版的加法器,我们需要客户端把要计算的两个加数发过去,然后由服务端进行计算,最后把计算结果返回给客户端。

按照这个思路,客户端每次应该发送两个加数和一个操作符,如果要把这些数据分三次发送或者两次发送,在一个服务端对应多个客户端的时候,数据就会混乱,便于避免,我们应该一次发送这些数据。一种方法,可以把数据和操作符整体看做一个字符串发送过去,然后服务端接收到后按照它们的约定正确的解析出数据和操作数(分割),进行计算,再把结果返回给客户端。再一种方法,我们可以定义一个结构体来表示每次要交互的信息,直接给服务端发送结构体,然后服务端按照它们的约定对数据进行计算,再把结果返回给客户端,这里要想想,如果你进行了除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)左边是服务端运行,右边是客户端运行呐
在这里插入图片描述

若有错误,欢迎指正:)
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值