Windows和Linux_c++写法_简易计算器_TCP

关键要点

如何在char数组中存储一个很大的数值

  • 第一位一定要是存储的数值
  • 示例以4字节作为一个数据的存储空间
#include<iostream>
using namespace std;
int main(int argc,char **argv)
{
    char p[8];
    //用4字节存储一个操作数
    //数组存数据时先取地址再转换类型
    int *a=(int*)&p[0];
    *a=1000;

    int *b=(int *)&p[4];
    *b=11111;
    //取数据时先转换char数组变为int数组,再解析数据
    int *p_int=(int*) p;
    for(int i=0;i<2;i++)
    {
        cout<<p_int[i]<<endl;
    }
    system("pause");
    return 0;
}

int类型转char *类型

该事项用于Windows服务端send(clntSock,(char*)&result,sizeof(result),0);,其中result类型原本为int,但由于send需要传输char *类型而进行的强制转换。

int b=1000;
char *a=(char*)&b;

Windows TCP简易计算器

服务端

#include <iostream>
#include <WinSock2.h>
#include <string.h>
using namespace std;
int calculate(int count,int *operand,char *ope)
{
    int res=operand[0];
    switch (ope[0])
    {
    case '+':
        for(int i=1;i<count;i++)
            res+=operand[i];
        break;
    case '-':
        for(int i=1;i<count;i++)
            res-=operand[i];
        break;
    case '*':
        for(int i=1;i<count;i++)
            res*=operand[i];
        break;
    case '/':
        for(int i=1;i<count;i++)
            res/=operand[i];
        break;
    }
    return res;
}
int main(int argc, char **argv)
{
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);
    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    sockaddr_in sock_addr;
    memset(&sock_addr, 0, sizeof(sock_addr));
    sock_addr.sin_family = AF_INET;
    sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    sock_addr.sin_port = htons(atoi(argv[1]));

    bind(sock, (sockaddr *)&sock_addr, sizeof(sock_addr));
    listen(sock, 5);

    SOCKADDR clntAddr;
    int nSize = sizeof(SOCKADDR);
    for (int i = 0; i < 5; i++)
    {

        SOCKET clntSock = accept(sock, (SOCKADDR *)&clntAddr,&nSize);
        // char count[4];
        char count[1];
        recv(clntSock,count,1,0);
        int operand_count=count[0];
        char operand[50];
        for(int i=0;i<operand_count;i++)
        {
            recv(clntSock,&operand[i*4],4,0);
            // cout<<operand[i]<<endl;
        }
        char ope[1];
        recv(clntSock,ope,1,0);
        int result=calculate(operand_count,(int*)operand,ope);
        char sendMsg[4];
        //int类型强制转换char*类型
        send(clntSock,(char*)&result,sizeof(result),0);
        closesocket(clntSock);
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}

客户端

#include<iostream>
#include<WinSock2.h>
#include<string.h>
#define BUFSIZE 50
#define OPSZ 4
using namespace std;
int main(int argc,char **argv)
{
    WSADATA wsa;
    WSAStartup(MAKEWORD(2,2),&wsa);
    char msg[BUFSIZE];
    SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN sock_addr;
    memset(&sock_addr,0,sizeof(sock_addr));
    sock_addr.sin_family=AF_INET;
    sock_addr.sin_addr.s_addr=inet_addr(argv[1]);
    sock_addr.sin_port=htons(atoi(argv[2]));

    connect(sock,(sockaddr*)&sock_addr,sizeof(sock_addr));
    cout<<"connected..."<<endl;
    int operand_count;
    cout<<"Operand count: ";
    cin>>operand_count;
    msg[0]=(char)operand_count;//注意范围为0=127
    for(int i=0;i<operand_count;i++)
    {
        cout<<"Operand "<<i+1<<": ";
        //将msg4个位作为一个数字的存储空间传输数值地址
        int *p=(int*)&msg[i*OPSZ+1];
        cin>>*p;
    }
    cout<<"Operator: ";
    cin>>msg[operand_count*OPSZ+1];
    send(sock,msg,operand_count*OPSZ+2,0);
    char res[4];
    recv(sock,res,OPSZ,0);
    int *res_num=(int*)res;//res得到的是数值的地址,需要先转换为(int*)类型,注意该类型为int数组指针
    cout<<"Operation result: "<<*res_num<<endl;
    closesocket(sock);
    WSACleanup();
    system("pause");
    return 0;
}

LINUX TCP简易计算器

服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUF_SIZE 50
#define OPSZ 4
void error_handling(char *message);
int calculate(int operand_count, int operands[], char ope);

int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    struct sockaddr_in serv_addr, clnt_addr;
    char message[BUF_SIZE];

    if (argc != 2)
    {
        printf("Usage : %s <port>", argv[0]);
        exit(1);
    }

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);

    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");

    socklen_t clnt_addr_sz = sizeof(clnt_addr);
    for (int i = 0; i < 5; i++)
    {
        if ((clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_sz)) == -1)
            error_handling("accept() error");

        int operand_count;
        read(clnt_sock, &operand_count, 1); // 首先读取第 1 个字节,获取操作数的数量

        char operands[BUF_SIZE];
        for (int i = 0; i < operand_count; i++)
        {
            read(clnt_sock, &operands[i * OPSZ], OPSZ); // 根据操作数数量,依次读取操作数
        }

        char ope;
        read(clnt_sock, &ope, 1); // 读取运算符

        int result = calculate(operand_count, (int *)operands, ope);
        write(clnt_sock, (char *)&result, sizeof(result)); // 发送计算结果
        close(clnt_sock);
    }
    close(serv_sock);
    return 0;
}

int calculate(int operand_count, int operands[], char ope)
{
    int result = operands[0];
    switch (ope)
    {
    case '+':
        for (int i = 1; i < operand_count; i++)
            result += operands[i];
        break;
    case '-':
        for (int i = 1; i < operand_count; i++)
            result -= operands[i];
        break;
    case '*':
        for (int i = 1; i < operand_count; i++)
            result *= operands[i];
        break;
    }
    return result;
}

void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<iostream>
using namespace std;
#define BUF_SIZE 50
#define OPSZ 4 // 定义每个操作数在 TCP 报文中占用的字节数

void error_handling(char *message);

int main(int argc, char *argv[])
{
    int sock;
    char opmsg[BUF_SIZE]; // opmsg 用来存储要发送的数据,注意是 char 类型数组
    struct sockaddr_in serv_addr;
    int operand_count, result;

    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)))
        error_handling("connect() error");
    else
        puts("Connecting..........\n");

    fputs("Operand count: ", stdout);
    // scanf("%d", &operand_count);
    cin>>operand_count;
    opmsg[0] = (char)operand_count; // 数据的第一个字节存储操作数的数量,注意要将变量类型转换为 char。

    for (int i = 0; i < operand_count; i++)
    {
        printf("Operand %d: ", i + 1);
        // scanf("%d", (int *)&opmsg[i * OPSZ + 1]); 
        // 从第二个字节开始每四个字节存储一个操作数,向数组存数据时先取地址再转换类型。
        //相当于在opmsg上放入p指针的地址
        int *p=(int*)&opmsg[i*OPSZ+1];
        cin>>*p;
    }

    fgetc(stdin);
    fputs("Operator: ", stdout);
    // scanf("%c", &opmsg[operand_count * OPSZ + 1]); // 再用一个字节存储运算符
    cin>>opmsg[operand_count*OPSZ+1];
    // cout<<"before write"<<endl;
    write(sock, opmsg, operand_count * OPSZ + 2); // 发送数据
    read(sock, &result, OPSZ);                    // 接收运算结果:运算结果是一个 4 字节的操作数

    printf("Operation result: %d\n", result);

    close(sock);
    return 0;
}

void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值