Strtok() 随机返回 NULL

  • 本文关键字:返回 NULL 随机 Strtok c
  • 更新时间 :
  • 英文 :


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

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

如果服务器收到操作,它将执行该操作并将结果返回给客户端。问题是我发送的第一个操作返回正确的结果,而接下来的操作随机工作(有时它们返回正确的结果,有时函数strtok()没有获得第二个操作数并返回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[] = "QUITn"; 
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, '', 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!nn");
} 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("%sn", &buffer[3]); 
} else {
fprintf(stderr, "Return Status = %d n", returnStatus);
}
memset(&buffer, '', 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("%sn", &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("%sn", operator);
printf("%sn", first);
char *second_operand = strtok(NULL, space);
printf("%sn", second_operand);
if (second_operand != NULL && strtok(NULL, space) == NULL && (atoi(first) > 0 || strcmp(first, "ANS") == 0)) {
if (strcmp(second_operand, "ANSn") == 0)
strcpy(second, "ANS");
else {
strcpy(second, second_operand);
}
if (atoi(second) > 0 || strcmp(second, "ANS") == 0) {
printf("OKn");
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("%sn", 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, '', sizeof(buffer));
memset(&first, '', sizeof(first));
memset(&second, '', sizeof(second));
memset(&message, '', sizeof(message));
memset(operator, '', sizeof(operator));
}
}

有人能告诉我为什么第二strtok()90%的时间表现得很奇怪吗?我做错了什么?

程序中存在多个问题:

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

在您的情况下,还有另一个更紧迫的问题:您read数据的缓冲区不是 null 终止的,因此您不应该将其传递给标准 C 函数,例如strtok()

最新更新