将 C 数组初始化为自定义字符
Initialize C array to custom character
我搭建了一个Winsock2服务器。该程序的一部分具有从客户端接收数据的功能。最初,我构建的接收函数会查看传入的数据,并在允许 recv()
从缓冲区中提取数据之前确定是否有任何其他数据要读取。这在项目开始时工作得很好,但我现在正在努力提高性能。
这是我为消除使用 peek 而编写的部分代码:
unsigned char recv_buffer[4096];
unsigned char *pComplete_buffer = malloc(sizeof(recv_buffer) * sizeof(unsigned char*));
int offset = 0;
int i = 0;
...
for (i; i <= sizeof(recv_buffer); i++) {
if (recv_buffer[i] == NULL) {
break;
}
pComplete_buffer[offset] = recv_buffer[i];
offset++;
}
...
这段代码可以很好地工作,但问题是 NULL == 0
。如果客户端碰巧发送 0
这个循环将提前中断。我以为我会很聪明,将未初始化的数据保留为 0xcc
并使用它来确定 recv_buffer
的结尾,但似乎客户有时也会将其作为数据的一部分发送。
问题:
有没有我可以初始化 recv_buffer
并可靠地中断的角色?
如果不是,是否有其他方法可以消除对 peek 的使用?
Is there a character I can initialize recv_buffer to and reliably break on?
没有。如果对方可以随时发送任何字符,则您必须检查它们。
如果您知道发件人永远不会连续发送 两个 NUL
([=11=][=11=]
),您可以检查一下。但是有一天发件人会决定这样做。
如果您可以更改消息结构,我会先发送消息长度(作为字节、网络排序的 short 或 int,具体取决于您的协议)。然后,在解析该长度后,接收者将确切知道要继续阅读多长时间。
此外,如果您使用的是 select
,它将阻塞直到有内容可读或套接字关闭(主要是——阅读文档)。
正确的解决方案是跟踪您在 recv_buffer
中存储的字节数。 sizeof()
为您提供了缓冲区的总可能大小,但它没有告诉您实际上有多少字节包含有效数据。
recv()
告诉你它 return 给你多少字节。当您将 recv()
数据写入 recv_buffer
时,使用该 return 值来递增您定义的变量以指示 recv_buffer
.
中的有效字节数
例如:
unsigned char recv_buffer[4096];
int num_read, recv_buffer_size = 0;
const int max_cbuffer_size = sizeof(recv_buffer) * sizeof(unsigned char*);
unsigned char *pComplete_buffer = malloc(max_cbuffer_size);
...
num_read = recv(..., recv_buffer, sizeof(recv_buffer), ...);
if (num_read <= 0) {
// error handling...
return;
}
recv_buffer_size = num_read;
...
int available = max_cbuffer_size - offset;
int num_to_copy = min(recv_buffer_size, available);
memcpy(pComplete_buffer + offset, recv_buffer, num_to_copy);
offset += num_to_copy;
memmove(recv_buffer, recv_buffer + num_to_copy, recv_buffer_size - num_to_copy);
recv_buffer_size -= num_to_copy;
...
我搭建了一个Winsock2服务器。该程序的一部分具有从客户端接收数据的功能。最初,我构建的接收函数会查看传入的数据,并在允许 recv()
从缓冲区中提取数据之前确定是否有任何其他数据要读取。这在项目开始时工作得很好,但我现在正在努力提高性能。
这是我为消除使用 peek 而编写的部分代码:
unsigned char recv_buffer[4096];
unsigned char *pComplete_buffer = malloc(sizeof(recv_buffer) * sizeof(unsigned char*));
int offset = 0;
int i = 0;
...
for (i; i <= sizeof(recv_buffer); i++) {
if (recv_buffer[i] == NULL) {
break;
}
pComplete_buffer[offset] = recv_buffer[i];
offset++;
}
...
这段代码可以很好地工作,但问题是 NULL == 0
。如果客户端碰巧发送 0
这个循环将提前中断。我以为我会很聪明,将未初始化的数据保留为 0xcc
并使用它来确定 recv_buffer
的结尾,但似乎客户有时也会将其作为数据的一部分发送。
问题:
有没有我可以初始化 recv_buffer
并可靠地中断的角色?
如果不是,是否有其他方法可以消除对 peek 的使用?
Is there a character I can initialize recv_buffer to and reliably break on?
没有。如果对方可以随时发送任何字符,则您必须检查它们。
如果您知道发件人永远不会连续发送 两个 NUL
([=11=][=11=]
),您可以检查一下。但是有一天发件人会决定这样做。
如果您可以更改消息结构,我会先发送消息长度(作为字节、网络排序的 short 或 int,具体取决于您的协议)。然后,在解析该长度后,接收者将确切知道要继续阅读多长时间。
此外,如果您使用的是 select
,它将阻塞直到有内容可读或套接字关闭(主要是——阅读文档)。
正确的解决方案是跟踪您在 recv_buffer
中存储的字节数。 sizeof()
为您提供了缓冲区的总可能大小,但它没有告诉您实际上有多少字节包含有效数据。
recv()
告诉你它 return 给你多少字节。当您将 recv()
数据写入 recv_buffer
时,使用该 return 值来递增您定义的变量以指示 recv_buffer
.
例如:
unsigned char recv_buffer[4096];
int num_read, recv_buffer_size = 0;
const int max_cbuffer_size = sizeof(recv_buffer) * sizeof(unsigned char*);
unsigned char *pComplete_buffer = malloc(max_cbuffer_size);
...
num_read = recv(..., recv_buffer, sizeof(recv_buffer), ...);
if (num_read <= 0) {
// error handling...
return;
}
recv_buffer_size = num_read;
...
int available = max_cbuffer_size - offset;
int num_to_copy = min(recv_buffer_size, available);
memcpy(pComplete_buffer + offset, recv_buffer, num_to_copy);
offset += num_to_copy;
memmove(recv_buffer, recv_buffer + num_to_copy, recv_buffer_size - num_to_copy);
recv_buffer_size -= num_to_copy;
...