c++ - 关于 C++ 套接字,为什么服务器总是返回相同的结果?

标签 c++ sockets c++11 winsock2

#include <WinSock2.h>
#include <cstdlib>
#include <cstdio>
#include <inaddr.h>

int calculate(int aopNum, int aopVal[], char aop) {
    int result = aopVal[0], i;

    switch(aop)
    {
        case '+':
            for(i = 1; i < aopNum; i++) result += aopVal[i];
            break;
        case '-':
            for(i = 1; i < aopNum; i++) result -= aopVal[i];
            break;
        case '*':
            for(i = 1; i < aopNum; i++) result *= aopVal[i];
            break;
    }

    return result;
}

int main() {
    WSADATA wsadata;

    const int bufSize = 1000;
    const int opSize = 4;
    int port = 5099;
   // int result;

    if(WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
        printf("Failed to init\n");
        return -1;
    } else {
        printf("Inited \n");
    }

    SOCKADDR_IN addrServ;
    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrServ.sin_family = AF_INET;
    addrServ.sin_port = htons(port);

    SOCKET  sockServ = socket(AF_INET, SOCK_STREAM, 0);

    if(bind(sockServ, (SOCKADDR *)&addrServ, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        printf("Fail to bind \n");
    } else {
        printf("Binded \n");
    }

    if(listen(sockServ, 10) == SOCKET_ERROR) {
        printf("Fail to listen \n");
    } else {
        printf("Listening \n");
    }
    fflush(stdout);
    SOCKADDR_IN addrClnt;
    int len = sizeof(addrClnt);

 //   SOCKET sockClnt = socket(AF_INET, SOCK_STREAM, 0);

    char bufRecv[bufSize];
    int  opnum;
    int recvLen = 0;

 //   SOCKET sockClnt;
    while(1) {
        SOCKET sockClnt = accept(sockServ, (SOCKADDR *)&addrClnt, &len);
        if(sockClnt == SOCKET_ERROR) {
            printf("Fail to accept \n");
            return -1;
        } else {
            printf("Accepted \n");
        }
        fflush(stdout);
        recv(sockClnt, (char *)&opnum, 1, 0);
        //int opnum = (int)(copnum - '0');
        printf("%d\n", opnum);
        fflush(stdout);
        while((opSize * opnum + 1) > recvLen) {
            int len1 = recv(sockClnt, &bufRecv[recvLen], bufSize - 1, 0);
            recvLen += len1;
        }
        printf("%c\n", bufRecv[recvLen - 1]);
        fflush(stdout);
    //testbegin:
        int *p = (int *)bufRecv;
        for(int j = 0; j < opnum; j++) {
            printf("%d ", p[j]);
            fflush(stdout);
        }


        int result = calculate(opnum, (int *)bufRecv, bufRecv[recvLen - 1]);
        printf("%d\n", result);
        fflush(stdout);
        send(sockClnt, (char *)&result, sizeof(result), 0);
        closesocket(sockClnt);
    }

    //closesocket(sockClnt);
    WSACleanup();
    return 0;
}

客户端.cpp:

#include <WinSock2.h>
#include <cstdlib>
#include <cstdio>
#include <inaddr.h>

int main() {
    WSADATA wsadata;

    const int bufSize = 1000;
    const int opSize = 4;

    int opNum;
    int port = 5099;
    int result;
//    char cresult;
    if(WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
        printf("Fail to init \n");
        return -1;
    }

    SOCKADDR_IN servAddr;
    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(port);
    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

    SOCKET sockClnt = socket(AF_INET, SOCK_STREAM, 0);

    if(connect(sockClnt, (SOCKADDR *)&servAddr, sizeof(servAddr)) != 0) {
        printf("Fail to connect \n");
    } else {
        printf("Connected \n");
    }
    fflush(stdout);
    char bufSent[bufSize];

    printf("Input the num of numbers: \n");
    fflush(stdout);
    scanf("%d", &opNum);
    bufSent[0] = (char)opNum;
    printf("Input the numbers \n");
    fflush(stdout);
    for(int i = 0; i < opNum; i++) {
        scanf("%d", (int *)&bufSent[1 + i * opSize]);
    }
    fgetc(stdin); 
    printf("Input the operator: \n");
    fflush(stdout);
    scanf("%c", &bufSent[1 + opNum * opSize]);

    send(sockClnt, bufSent, opNum * opSize + 2, 0);
    recv(sockClnt, (char *)&result, sizeof(result), 0);

    printf("The result is %d", result);
    fflush(stdout);
   // delay(5);
    closesocket(sockClnt);
    WSACleanup();
    return 0;
}

问题是在运行服务器后,我启动了一个客户端并输入:

3
2
4
6
*

它可以正确返回2 * 4 * 6 = 48。但是,当我在不停止服务器的情况下启动新客户端时,我输入:

3 
2
4
6
+

它仍然返回 48(而不是 2 + 4 + 6 = 12,即使我输入 3 1 2 3,它仍然返回 48)。我尝试了很多但仍然无法解决。所以我现在在这里寻求帮助。

最佳答案

那个 recvLen 变量应该被移动到 while(1) 循环中:

while (1) {
int recvLen = 0;

它包含来自先前连接的值,并且值/运算符的位置不清楚(未完全检查)。多次连接后,如果不进行更改,代码也会崩溃(缓冲区指针始终移动,缓冲区是堆栈上的静态数组)

线

recv(sockClnt, (char *)&opnum, 1, 0);

是危险的 .. 它将单个字节读入一个整数。该 int 的 3 个字节不受影响,可能包含未初始化的内存。更好的方法是传输一个整数(4 字节)或至少变量必须设置为 0:

int  opnum = 0;

关于c++ - 关于 C++ 套接字,为什么服务器总是返回相同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58061792/

相关文章:

c++ - 双轴快速排序

c++ - 在 C++ 中避免继承层次结构中的重复代码

c++ - 使用GLUT中的按键旋转

c++ - 如何在一个窗口中有多个布局?

c# - 在system.net.socket中将HTTP header 发送到客户端的实际方法

JavaMail 和 IP4 与 IP6

c++ - 如何在干净的代码中向后遍历双向迭代器?

javascript - Python 到 javascript 通信

c++ - 在 operator()() 中对具有状态和两个参数的函数对象使用 boost bind

c++11 - std::pair 的 switch 语句?