网络版计算器
- 1.程序简介
- 2.思路
- 3.代码实现
- 4.运行结果
1.程序简介
- 我们想要实现一个服务器版的简易计算器,我们需要从客户端发送两个数据以及所要操作的类型,然后由服务器进行处理,并将结果返回至客户端
2.思路
- 这种运算的规则,我们也可以认为是一种协议,因为是客户端与服务端达成的某种约定
- 我们需要定义两个结构体去表示客户端与服务端之间进行交互的信息
- 发送数据时将这个结构体按照一个规则转换成字符串,接收数据的时候再按照相同的规则把字符串转化为结构体
- 这个过程就叫做
序列化
和反序列化
3.代码实现
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
#ifndef __CLIENT_HPP__
#define __CLIENT_HPP__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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)
{
request_t rq;
response_t rsp = {4,0};
ssize_t s = recv(sock, &rq, sizeof(rq), 0);
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
#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;
}
#ifndef __SERVER_HPP__
#define __SERVER_HPP__
#include
#include
#include
#include
#include
#include
#include
#include
#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)
{
request_t rq;
response_t rsp = {4,0};
ssize_t s = recv(sock, &rq, sizeof(rq), 0);
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);
cal(sock);
exit(0);
}
close(lsock);
waitpid(-1,nullptr,0);
}
}
~server()
{
close(lsock);
}
};
#endif
#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;
}
#ifndef __PROTOCOL_HPP__
#define __PROTOCOL_HPP__
#include
typedef struct request
{
int x;
int y;
char op;
}request_t;
typedef struct response
{
int code;
int result;
}response_t;
#endif
4.运行结果