如何使用strtok解析TCP服务器字符串?Socket通信无输出问题排查
Socket通信中移除"\r"分隔符解析字符串无输出问题排查与解决
问题描述
编写了一段监听服务器的程序,使用"\r"作为分隔符。但运行该程序后没有任何输出,请问如何在Socket通信中移除分隔符来解析字符串?
客户端代码
#include <arpa/inet.h> // inet_addr() #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> // bzero() #include <sys/socket.h> #include <unistd.h> // read(), write(), close() #define MAX 80 #define PORT 8080 #define SA struct sockaddr void func(int sockfd) { char buff[MAX]; int n; char str[MAX]; for (;;) { bzero(buff, sizeof(buff)); printf("Enter the string : "); n = 0; while ((buff[n++] = getchar()) != '\n') ; write(sockfd, buff, sizeof(buff)); bzero(buff, sizeof(buff)); read(sockfd, buff, sizeof(buff)); strcpy(str,buff); char delim[]="\r"; char *str = strtok(str,delim); while(str != NULL) { printf("from my prog = %s \n",str); str = strtok(NULL,delim); } if ((strncmp(buff, "exit", 4)) == 0) { printf("Client Exit...\n"); break; } } }
通信数据截图

问题排查与解决
你的代码存在几个关键问题,直接导致程序无输出:
1. 变量重定义覆盖
代码中先定义了char str[MAX];,后续又用char *str = strtok(str,delim);重新定义同名指针变量,这会覆盖之前的数组变量,导致strtok操作的内存地址异常,无法正确解析字符串。
修复:把指针变量名改成不同的,比如token:
char *token = strtok(str, delim); while (token != NULL) { printf("from my prog = %s \n", token); token = strtok(NULL, delim); }
2. 未处理read()返回值
read()函数可能返回0(服务器关闭连接)、-1(读取错误),或者实际读取的字节数。直接使用buff会导致读取空数据或错误数据,进而解析失败无输出。
修复:添加返回值判断,并手动给buff添加字符串终止符(\0),避免乱码:
ssize_t bytes_read = read(sockfd, buff, sizeof(buff)-1); if (bytes_read <= 0) { if (bytes_read == 0) { printf("Server closed connection\n"); } else { perror("read failed"); } break; } buff[bytes_read] = '\0'; // 确保字符串以\0结尾
3. 发送冗余数据
当前代码用write(sockfd, buff, sizeof(buff))发送整个80字节的缓冲区,而你输入的字符串长度远小于80,剩余字节都是空字符,这会导致服务器收到冗余数据,返回的内容可能不符合预期。
修复:只发送实际输入的字节数:
// 读取输入时限制长度,避免溢出 n = 0; while ((buff[n++] = getchar()) != '\n' && n < MAX-1); // 发送实际输入的字节数(包括换行符\n) write(sockfd, buff, n);
4. 分隔符适配问题
从截图看,服务器返回的数据结尾是\r\n,只用\r做分隔符的话,解析后的字符串会带有\n,如果需要去除,可以在解析后处理:
while (token != NULL) { size_t len = strlen(token); // 去掉末尾的换行符\n if (len > 0 && token[len-1] == '\n') { token[len-1] = '\0'; } printf("from my prog = %s \n", token); token = strtok(NULL, delim); }
修正后的完整func函数
void func(int sockfd) { char buff[MAX]; char str[MAX]; for (;;) { bzero(buff, sizeof(buff)); printf("Enter the string : "); int n = 0; // 读取输入,避免缓冲区溢出 while ((buff[n++] = getchar()) != '\n' && n < MAX-1); // 发送实际输入的字节数 write(sockfd, buff, n); bzero(buff, sizeof(buff)); // 读取服务器返回数据并处理返回值 ssize_t bytes_read = read(sockfd, buff, sizeof(buff)-1); if (bytes_read <= 0) { if (bytes_read == 0) { printf("Server closed connection\n"); } else { perror("read failed"); } break; } buff[bytes_read] = '\0'; strcpy(str, buff); // 用\r作为分隔符解析字符串 char delim[] = "\r"; char *token = strtok(str, delim); while (token != NULL) { // 移除末尾的\n(如果存在) size_t len = strlen(token); if (len > 0 && token[len-1] == '\n') { token[len-1] = '\0'; } printf("from my prog = %s \n", token); token = strtok(NULL, delim); } if (strncmp(buff, "exit", 4) == 0) { printf("Client Exit...\n"); break; } } }
内容的提问来源于stack exchange,提问作者user20496966
相关产品推荐
相关产品推荐

