简体   繁体   中英

Initialize C array to custom character

I have built a Winsock2 server. Part of that program has a function that receives data from clients. Originally the receive function I built would peek at the incoming data and determine if there was any additional data to be read before allowing recv() to pull the data from the buffer. This worked fine in the beginning of the project but I am now working on improving performance.

Here is a portion of the code I've written to eliminate the use of 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++;
    }

    ...

This code would work great but the problem is that NULL == 0 . If the client happens to send a 0 this loop will break prematurely. I thought I would be clever and leave the data uninitialized to 0xcc and use that to determine the end of recv_buffer but it seems that clients sometimes send that as part of their data as well.

Question:

Is there a character I can initialize recv_buffer to and reliably break on?

If not, is there another way I can eliminate the use of peek?

The correct solution is to keep track of how many bytes you store in recv_buffer to begin with. sizeof() gives you the TOTAL POSSIBLE size of the buffer, but it does not tell you HOW MANY bytes actually contain valid data.

recv() tells you how many bytes it returns to you. When you recv() data into recv_buffer , use that return value to increment a variable you define to indicate the number of valid bytes in recv_buffer .

For example:

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;

...

Is there a character I can initialize recv_buffer to and reliably break on?

Nope. If the other side can send any character at any time, you'll have to examine them.

If you know the sender will never send two NUL s in a row ( \\0\\0 ), you could check for that. But then some day the sender will decide to do that.

If you can change the message structure, I'd send the message length first (as a byte, network-ordered short or int depending on your protocol). Then, after parsing that length, the receiver will know exactly how long to keep reading. Also if you're using select , that will block until there's something to read or the socket closes (mostly -- read the docs).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM