【问题标题】:what is wrong with the following while loop?下面的while循环有什么问题?
【发布时间】:2017-10-21 07:59:13
【问题描述】:

我有一个 c winsock 代码部分,客户端在其中接收逗号分隔的文件指纹流,如下所示。我需要在 while 循环中使用 strtok_s() 从流中提取指纹。我的问题是大多数时候客户端没有提取从服务器发送的确切数量的指纹,即使接收到的数据(通过调试观察)正是服务器发送的数据。 我在这里错过了什么?

recv_size = recv(clnt_sock, fp_buf, BUF_LEN, 0);
            received_fp_size += recv_size;
        if (0 != (last_string_len = recv_size % 33))
            strncpy(last_string, &fp_buf[(recv_size - last_string_len)], last_string_len);//
        while (recv_size > 0)
        {
            unique_fp = strtok_s(fp_buf, ",", &strtk);
        k:
            while (unique_fp != NULL)
            {
                memcpy(unique_fp_buf[unique_files_count], unique_fp, 32);
                unique_fp = strtok_s(NULL, ",", &strtk);
                unique_files_count++;

            }


            recv_size = recv(clnt_sock, fp_buf, BUF_LEN, 0);
            received_fp_size += recv_size;
            if (last_string_len > 0)
            {
                unique_fp = strtok_s(fp_buf, ",", &strtk);
                strncat_s(last_string, unique_fp, strlen(unique_fp));
                memcpy(unique_fp, last_string, 32);
                last_string_len = 0;
                goto k;
            }

        }

if (0 != (last_string_len = recv_size % 33)) 行背后的原因是;服务器发送多个 33 字节字符串(32 用于指纹,1 用于逗号分隔符)

【问题讨论】:

  • 第一个建议:不要使用 'goto()` 函数第二个建议:格式化代码以提高可读性。
  • 问题是关于运行时问题。所以发布的代码必须干净地编译并且是可执行的。在给定输入数据和所需输出的情况下,还包括一些示例输入数据和实际输出。
  • 发布的代码包含一个“神奇”数字。一个“神奇”的数字是没有根据的。即 33。 “神奇”数字使代码更难理解、调试等。建议通过enum#define 语句为该“神奇”数字指定一个有意义的名称,然后在整个代码中使用该有意义的名称
  • 在最后一个if() 块中,这一行:memcpy(unique_fp, last_string, 32); 损坏了unique_fp 指向的内存。
  • read()的调用应该类似于:`recv_size = recv(clnt_sock, fp_buf+last_string_len, BUF_LEN-last_string_len, 0); recv_size += last_string_len;

标签: c sockets while-loop winsock strtok


【解决方案1】:

一个问题是您永远不会检查fp_buf 是否确实包含完整的令牌。例如,如果第一次调用仅接收 20 个字节,您的代码将因复制部分指纹而失败。

我认为还有一个问题:

memcpy(unique_fp, last_string, 32);

您似乎正在复制到接收缓冲区,因此覆盖了一些您尚未处理的数据。此外,您可以覆盖令牌。

也许你真的想要:

memcpy(unique_fp_buf[unique_files_count], last_string, 32);
                                          ^^^^^^^^^^^
unique_fp = strtok_s(NULL, ",", &strtk);
unique_files_count++;

除此之外,我认为您使代码比需要的复杂得多。 goto 的使用告诉你你的设计是错误的。

您可以这样做,而不是使用last_string

1) Call recv
2) Process all complete fingerprints
3) Copy the remainder (i.e. the last partial fingerprint) to the start of `fp_buf`
4) Call `recv` with an offset into `fp_buf`
5) Repeat from step 2 (i.e. use a while loop - don't use goto

第 3 步可能类似于:

recv_size = recv(clnt_sock, fp_buf + length_of_remainder , BUF_LEN -  length_of_remainder, 0);

这样你就不必处理 last_string 的东西了

【讨论】:

    猜你喜欢
    • 2020-07-09
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 2013-01-19
    相关资源
    最近更新 更多