简体   繁体   中英

Fastest way of reading from socket and converting bytes C++

I'm wondering which is the fastest way of implementing this kind of algorithm in C++ : I have a source of data that comes over TCP/IP so I read all data from a single socket. I have a flow of bytes that represent and integer of 4 bytes. So the two alternative are:

  1. read all bytes until the end(saving them into a very big array of unsigned char ) and then convert them all . Pro: I read "only one" time from the socket(I know that read() function reads as mush as it can but lets say that this always happens). Cons: save all bytes into an array but in this way I have to pay the cost of looping over the array, where I saved the bytes, loosing time in memory accesses.

  2. read 4 bytes at a time and convert just them. Pro: no memory accesses because I do not save all bytes into a very big array but just in a small array of 4 bytes. Cons: I have to call read(sockfd,buff,4) too many times.

What do you think is the best way in terms of performance on your opinion and experience?

On modern architectures, CPU cycles are going to be faster that network bandwidth.

Unless your "conversion" process is very CPU intensive, it's going to be better to convert whatever data comes in, before attempting to read more.

In most cases, it may not even be necessary to go full throttle with non-blocking sockets, and an event-handling design. A simple approach -- just read whatever can be read into a reasonably-sized buffer, say 64kb, "convert" it, then read again -- should work well. Note -- not 4 bytes at a time, that's horribly inefficient -- but with a large buffer like 64kb, then convert as many 4-byte words that were read, then save any remaining 1-3 bytes to be merged with the next read attempt.

Because if you just try to read again, immediately, chances are you'll just be waiting for the next chunk of packets to arrive. Might as well make a better use of that time by chewing through the just-read data.

You do want to make sure that your conversion process is fast enough so that you're keeping pace with the incoming data. You don't want to fall behind. So, if your conversion process could be time-consuming, then it's better to use non-blocking sockets, and process a reasonably-small chunk of data, before attempting to read more data, to buffer ahead.

recv() or read() a socket(), buffer.

You can do something like this:

#define BUFFER_SIZE 1024

char buffer[BUFFER_SIZE];

while(read(fd, buffer, BUFFER_SIZE - 1) != 0){
        fprintf(stderr, "%s", buffer);
        bzero(buffer, BUFFER_SIZE);
}

send() or write() a socket

To send a whole gob of data and it just can't handle it, It'll fire off as much of the data as it can, and trust you to send the rest later.

#include <sys/types.h>
#include <sys/socket.h>

int sendall(int s, char *buf, int *len)
{
        int total = 0;        // how many bytes we've sent
        int bytesleft = *len; // how many we have left to send
        int n;

        while(total < *len) {
                n = send(s, buf+total, bytesleft, 0);
                if (n == -1) { break; }
                total += n;
                bytesleft -= n;
        }

        *len = total; // return number actually sent here

        return n==-1?-1:0; // return -1 on failure, 0 on success
}

Call the function

char buf[20] = "Hello World!";
int len;

len = strlen(buf);
if (sendall(s, buf, &len) == -1) {
        perror("sendall");
        printf("We only sent %d bytes because of the error!\n", len);
} 

I have a flow of bytes that represent and integer of 4 bytes. So the two alternative are:

  • Read all bytes until the end(saving them into a very big array of unsigned char) and then convert them all.
  • Read 4 bytes at a time and convert just them.

You can read them in a buffer of int directly (no conversion needed):

int buff[1024];
int result = read(sockfd, buff, sizeof(buff));
// check result

// access the `int`'s directly without conversion
int test = buff[0];

Depending on the endianess, you might need to convert those int 's with htonl() or ntohl() .

I wouldn't read everything in one big buffer only to start processing the data after a full download, because processing the data will probably be faster than the download speed.

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