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

About C++ socket, why does server always return the same result?

本文关键字:返回 结果 套接字 C++ 为什么 服务器 关于      更新时间:2023-10-16
#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 initn");
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("%dn", opnum);
fflush(stdout);
while((opSize * opnum + 1) > recvLen) {
int len1 = recv(sockClnt, &bufRecv[recvLen], bufSize - 1, 0);
recvLen += len1;
}
printf("%cn", 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("%dn", 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;