以下 while 循环有什么问题?
what is wrong with the following while loop?
我有一个 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 个用于逗号分隔符)
一个问题是您从不检查 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
东西
我有一个 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 个用于逗号分隔符)
一个问题是您从不检查 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
东西