Linux——实现一个简单的网络版计算器

1.程序简介

  • 我们想要实现一个服务器版的简易计算器,我们需要从客户端发送两个数据以及所要操作的类型,然后由服务器进行处理,并将结果返回至客户端

2.思路

  • 这种运算的规则,我们也可以认为是一种协议,因为是客户端与服务端达成的某种约定
  • 我们需要定义两个结构体去表示客户端与服务端之间进行交互的信息
  • 发送数据时将这个结构体按照一个规则转换成字符串,接收数据的时候再按照相同的规则把字符串转化为结构体
  • 这个过程就叫做序列化反序列化

3.代码实现

  • Makfile
FlAG =-std=c++11 -lpthread

.PHONY:all	
all:Client Server

Client:Client.cc
	g++ -o $@ $^ $(FLAG) static 
Server:Server.cc
	g++ -o $@ $^ $(FLAG) -g  

.PHONY:clean
clean:
	rm -f Client Server
  • Client.cc
#ifndef __CLIENT_HPP__
#define __CLIENT_HPP__


#include<iostream>
#include<string>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include"Protocol.hpp"
using namespace std;
class client
{
  private:
    int port;
    int sock;
    string ip;
  public:
    client(string _ip, int _p)
      :ip(_ip)
      ,port(_p)
      ,sock(-1)
    {}

    void initClient()
    {
      sock = socket(AF_INET, SOCK_STREAM, 0);
      if(sock < 0)
      {
        cerr << "socket error" << endl;
        exit(2);
      }
    }

    void cal(int sock)
    {
      //短链接来完成对应的计算 就是A发一个请求 B处理一个 B申请断开连接 
      request_t rq;
      response_t rsp = {4,0};//默认从4开始
      ssize_t s = recv(sock, &rq, sizeof(rq), 0);//有BUG
      if(s > 0)
      {
        switch(rq.op)
        {
          case '+':
            rsp.result = rq.x + rq.y;
            break;
          case '-':
            rsp.result = rq.x - rq.y;
            break;
          case '*':
            rsp.result = rq.x * rq.y;
            break;
          case '/':
            if(rq.y != 0)
            {
              rsp.result = rq.x / rq.y;
            }
            else 
            {
              rsp.code = 2;
            }
            break;
          case '%':
            if(rq.y != 0)
            {
              rsp.result = rq.x % rq.y;
            }
            else 
            {
              rsp.code = 2; 
            }
            break;
          default:
            //走到这里说明 操作符不对
            rsp.code = 3;
            break;
        }
      }
      send(sock, &rsp, sizeof(rsp), 0);
      close(sock);

    }

    void start()
    {
      struct sockaddr_in server;
      server.sin_family = AF_INET;
      server.sin_port = htons(port);
      server.sin_addr.s_addr = inet_addr(ip.c_str());

      if(connect(sock ,(struct sockaddr*)&server, sizeof(server)) <  0)
      {
        cerr << "connect error!\n" << endl;
        exit(2);
      }

      request_t rq;
      response_t rsp;
      cout << "data1# ";
      cin >> rq.x;
      cout << "data2# ";
      cin >> rq.y;
      cout << "op#";
      cin >> rq.op;

      send(sock,&rq,sizeof(rq),0);
      recv(sock,&rsp,sizeof(rsp),0);

      cout << "code : " << rsp.code << endl;
      cout << "rersult : " << rsp.result << endl;
    }
    ~client()
    {
      close(sock);
    }
};

#endif 
  • Client.cc
#include "Client.hpp"


void Menu(string proc)
{
  cout << " usage : \n\t";
  cout << proc << "svr_ip svr_port" << endl;
}
int main(int argc, char *argv[])
{
  if(argc != 3)
  {
    Menu(argv[0]);
    exit(1);
  }

  client *cp = new client(argv[1],atoi(argv[2]));
  cp->initClient();
  cp->start();

  return 0;
}
  • Server.hpp
#ifndef __SERVER_HPP__
#define __SERVER_HPP__


#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include"Protocol.hpp"
using namespace std;
class server
{
  private:
    int port;
    int lsock;
  public:
    server(int _p):port(_p)
    {}

    void initServer()
    {
      lsock = socket(AF_INET, SOCK_STREAM, 0);
      if(lsock < 0)
      {
        cerr << "socket error" << endl;
        exit(2);
      }
      struct sockaddr_in local;
      local.sin_family = AF_INET;
      local.sin_port = htons(port);
      local.sin_addr.s_addr = INADDR_ANY;
      //开始绑定
      if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0)
      {
        cerr << "bind error !" << endl;
        exit(3);
      }
      if(listen(lsock, 5) < 0)
      {
        cerr << "listen error!\n" << endl;
      }
    }

    void cal(int sock)
    {
      //短链接来完成对应的计算 就是A发一个请求 B处理一个 B申请断开连接 
      request_t rq;
      response_t rsp = {4,0};//默认从4开始
      ssize_t s = recv(sock, &rq, sizeof(rq), 0);//有BUG
      if(s > 0)
      {
        switch(rq.op)
        {
          case '+':
            rsp.result = rq.x + rq.y;
            break;
          case '-':
            rsp.result = rq.x - rq.y;
            break;
          case '*':
            rsp.result = rq.x * rq.y;
            break;
          case '/':
            if(rq.y != 0)
            {
              rsp.result = rq.x / rq.y;
            }
            else 
            {
              rsp.code = 2;
            }
            break;
          case '%':
            if(rq.y != 0)
            {
              rsp.result = rq.x % rq.y;
            }
            else 
            {
              rsp.code = 2; 
            }
            break;
          default:
            //走到这里说明 操作符不对
            rsp.code = 3;
            break;
        }
      }
      send(sock, &rsp, sizeof(rsp), 0);
      close(sock);

    }

    void start()
    {
      struct sockaddr_in peer;
      for(;;)
      {
        socklen_t len = sizeof(peer);
        int sock = accept(lsock, (struct sockaddr*)&peer,&len);
        if(sock < 0)
        {
          cerr << "accept error!\n" << endl;
          continue;
        }
        if(fork() == 0)
        {
          if(fork() > 0)
          {
            exit(0);
          }
          //孙子
          close(lsock);
          //todo
          cal(sock);
          exit(0);
        }
        close(lsock);
        waitpid(-1,nullptr,0);
      }
    }
    ~server()
    {
      close(lsock);
    }
};

#endif 
  • Server.cc
#include "Server.hpp"


void Menu(string proc)
{
  cout << " usage : \n\t";
  cout << proc << "port" << endl;
}
int main(int argc, char *argv[])
{
  if(argc != 2)
  {
    Menu(argv[0]);
    exit(1);
  }

  server *sp = new server(atoi(argv[1]));
  sp->initServer();
  sp->start();

  return 0;
}
  • Protocol.hpp
#ifndef __PROTOCOL_HPP__
#define __PROTOCOL_HPP__  

#include<iostream>

typedef struct request
{
  int x;
  int y;
  char op;//操作符
}request_t;

typedef struct response
{
  int code;//状态码 对应不同的错误情况
  int result;
}response_t;

#endif  

4.运行结果

在这里插入图片描述

  • 19
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值