Strtok()随机返回NULL

时间:2018-09-02 17:01:30

标签: c

我正在尝试通过发送两种类型的消息来创建与服务器通信的客户端:

  1. 与服务器通信以关闭连接的单词QUIT
  2. 具有以下语法的操作:运算符first_operand second_operand。例如:+ 3 3- 5 6等(操作数必须是正整数,并且只能有2个操作数)。

如果服务器收到操作,它将执行该操作并将结果返回给客户端。问题是我发送的第一个操作返回正确的结果,而随后的操作随机工作(有时它们返回正确的结果,而其他时候函数strtok()没有获得第二个操作数并返回{{1} } ...)。

这是客户端的代码,用于处理用户在提示中编写的消息,并扫描消息以检查操作是否使用正确的语法编写(警告:以一种非常不专业和不干净的方式。

造成问题的代码部分位于NULL内部。

while(1)

有人可以告诉我为什么第二个#define MAXLENGTH 256 int main (int argc, char *argv[]) { int simpleSocket = 0; int simplePort = 0; int returnStatus = 0; char first[10], second[10]; char* operator; char buffer[MAXLENGTH] = ""; char message[50]; char terminationCommand[] = "QUIT\n"; char space[2] = " "; struct sockaddr_in simpleServer; if (3 != argc) { fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]); exit(1); } /* create a streaming socket */ simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (simpleSocket == -1) { fprintf(stderr, "Could not create a socket!\n"); exit(1); } else { fprintf(stderr, "Socket created!\n"); } /* retrieve the port number for connecting */ simplePort = atoi(argv[2]); /* setup the address structure */ /* use the IP address sent as an argument for the server address */ //bzero(&simpleServer, sizeof(simpleServer)); memset(&simpleServer, '\0', sizeof(simpleServer)); simpleServer.sin_family = AF_INET; //inet_addr(argv[2], &simpleServer.sin_addr.s_addr); simpleServer.sin_addr.s_addr=inet_addr(argv[1]); simpleServer.sin_port = htons(simplePort); /* connect to the address and port with our socket */ returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer)); if (returnStatus == 0) { fprintf(stderr, "Connect successful!\n\n"); } else { fprintf(stderr, "Could not connect to address!\n"); close(simpleSocket); exit(1); } /* get the message from the server */ returnStatus = read(simpleSocket, buffer, sizeof(buffer)); if (returnStatus > 0) { printf("%s\n", &buffer[3]); } else { fprintf(stderr, "Return Status = %d \n", returnStatus); } memset(&buffer, '\0', sizeof(buffer)); printf("You can execute 2 commands:\n"); printf("1. Operations ( +, -, *, /, % ) with the following syntax: operator + first operand + second operand.\n"); printf("Example: + 5 2 \n"); printf("2. Termination of the connection with the following syntax: QUIT + press Enter.\n"); while(1) { printf("\nEnter a command:\n"); fgets(message, 1000, stdin); // the if with the termination command works fine if (strcmp(message, terminationCommand) == 0) { if (send(simpleSocket, message, strlen(message), 0) < 0) { printf("Send failed."); return 1; } returnStatus = read(simpleSocket, buffer, sizeof(buffer)); if (returnStatus > 0) { printf("%s\n", &buffer[4]); } else { fprintf(stderr, "Return Status = %d \n", returnStatus); } close(simpleSocket); exit(1); } operator = strtok(message, space); if (strcmp(operator, "+") == 0 || strcmp(operator, "-") == 0 || strcmp(operator, "/") == 0 || strcmp(operator, "%") == 0 || strcmp(operator, "*") == 0) { char *first_operand = strtok(NULL, space); if (first_operand != NULL) { if (strcmp(first_operand, "ANS") == 0) strcpy(first, "ANS"); else strcpy(first, first_operand); printf("%s\n", operator); printf("%s\n", first); char *second_operand = strtok(NULL, space); printf("%s\n", second_operand); if (second_operand != NULL && strtok(NULL, space) == NULL && (atoi(first) > 0 || strcmp(first, "ANS") == 0)) { if (strcmp(second_operand, "ANS\n") == 0) strcpy(second, "ANS"); else { strcpy(second, second_operand); } if (atoi(second) > 0 || strcmp(second, "ANS") == 0) { printf("OK\n"); char operation[] = ""; strcat(operation, operator); strcat(operation, " "); strcat(operation, first); strcat(operation, " "); strcat(operation, second); if (send(simpleSocket, operation, strlen(operation), 0) < 0) { printf("Send failed."); return 1; } returnStatus = read(simpleSocket, buffer, sizeof(buffer)); if (returnStatus > 0) { printf("%s\n", buffer); } else { fprintf(stderr, "Return Status = %d \n", returnStatus); } } } } } // after everything I reset the buffers I use to memorize the message and the elements of the message memset(&buffer, '\0', sizeof(buffer)); memset(&first, '\0', sizeof(first)); memset(&second, '\0', sizeof(second)); memset(&message, '\0', sizeof(message)); memset(operator, '\0', sizeof(operator)); } } 的行为奇怪的是90%吗?我在做什么错了?

1 个答案:

答案 0 :(得分:0)

您的程序中存在多个问题:

您发送换行符终止的消息,并且假设另一端read将准确返回另一方发送的字节,这对于TCP / IP通信来说是错误的假设,仅接收到字节的顺序是保证的,但是消息可以在途中拆分,并以不同于发送顺序的块接收。相反,您应该将套接字读取到缓冲区中,并且仅在收到换行符后才对其进行处理。

在您的情况下,还有另一个问题迫在眉睫:read数据所在的缓冲区没有以空值终止,因此您不应将其传递给标准C函数,例如strtok()