如何清空套接字上read()函数的缓冲区

5

我正在尝试从服务器接收数据,第一次工作正常,但是随着read()的循环,它也会存储先前读取的旧值。以下是我目前的代码。

        char receive[50];

        if((he = gethostbyname(servername)) == NULL ) {

            perror(strcat("Cannot find server named:", servername));
            exit(0);
        }

        he = gethostbyname("localhost");
        localIP = inet_ntoa(*(struct in_addr *)*he->h_addr_list);
        client_sock_desc = socket(AF_INET, SOCK_STREAM, 0);
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = inet_addr(localIP);
        server_addr.sin_port = htons(serverport);
        len = sizeof(server_addr);
        if(connect(client_sock_desc, (struct sockaddr *)&server_addr,len) == -1) {
            perror("Client failed to connect");
            exit(0);
        }

        strcpy(buf, "CLIENT/REQUEST\n");
        send(client_sock_desc, buf, strlen(buf), 0);
        //send actual function request

        //put a space before \n char to make it easier for the server
        for(i = 0; i < sizeof(wholeRequest); i++) {
            if(wholeRequest[i] == '\n') {
                wholeRequest[i] = ' ';
                wholeRequest[i+1] = '\n';
                break;
            }
        }

        while(read(client_sock_desc, receive, sizeof(receive)) > 0) {
            strcpy(receive, ""); //attempt to erase all old values
            printf(receive);
            fflush(stdout);
        }
        close(client_sock_desc);

当服务器发送数据并关闭套接字时,它可以正常工作。但是当我让客户端再次打开套接字,向服务器发送数据时,服务器会再次将数据发送到客户端并关闭套接字。客户端将再次尝试读取服务器发送的数据,但这次它会在接收中填充新信息和旧信息的一部分。

2
你的服务器返回空终止字符串吗?我认为设置 receive[0]='\0' 是清除字符串的好方法。因为在你打印输出之前,你已经“清除”了 receive,那么你怎么能得到任何输出呢?难道是因为你需要 printf("%s", receive) 吗?我不确定当格式字符串为 ""printf 的反应如何... - Floris
我在打印输出后会“清除”接收内容,这样当我再次执行read()时,它将填充一个空的receive,只包含从服务器接收到的当前值。 - user2158382
1
不,你在strcpy行中“清除”了接收,在你上面的代码中,这发生在printf之前。 fflush只是意味着printf要输出到stdout的所有内容实际上在执行下一行之前都会传输到控制台。那就是“刷新缓冲区”,而你正在对输出进行操作。 - Floris
1个回答

5

在您的代码中,似乎在打印数据之前删除了接收到的数据 - 然后将空字符串传递给printf,我不确定printf会对此做什么(因为格式化字符串为空)。

尝试这个:

int nread;
while((nread = read(client_sock_desc, receive, sizeof(receive)-1)) > 0) {
        receive[nread]='\0';    // explicit null termination: updated based on comments
        printf("%s\n",receive); // print the current receive buffer with a newline
        fflush(stdout);         // make sure everything makes it to the output
        receive[0]='\0';        // clear the buffer : I am 99% sure this is not needed now
    }

当你的评论出现时,我正在编辑带有修复程序的问题...计算读取的字符数,然后手动在正确的位置附加 '\0'。比整个缓冲区填充零更不可靠... - Floris
1
顺便说一下,即使我在接收的地方添加了'\0',它仍然包含旧结果的数据。这是我尝试后得到的一些数据:输入命令: multiply 1 2 3 服务器/结果 multiply 1 2 3 6 输入命令: multiply 2 1 服务器/不匹配 multiply 2 3 ** 6**。加粗的字符不应该出现在结果中,它来自旧值。 - user2158382
你的 printf 不应该打印超过空字符终止符!让我们进行调试。将你的 printf 代码更改为:printf("字符数:%d;字符串:%s\n", nread, receive);。你是否注意到我正在读取 sizeof(receive)-1 个字符,而不是 sizeof(receive) - Floris
还有一件事:你说“循环遍历了接收字符串的1024个索引”,但是你之前用char receive[50];保留了一个只有50个字符的块。你是否覆盖了其他变量? - Floris
抱歉,实际上我的意思是receive[1024]。但我将在5分钟内尝试您的修复,我只是想快速尝试修复另一个问题。 - user2158382
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接