Самый быстрый способ отправить несколько массивов символов через TCP - PullRequest
1 голос
/ 12 марта 2019

Я работаю над фреймворком веб-сервера в C ++ в основном для собственного понимания, но я также хочу оптимизировать его.

Мой вопрос заключается в том, быстрее ли записывать несколько массивов символов в TCP-соединение для каждого html-ответа или тратить время на предварительную конкатенацию и запись в TCP-соединение только один раз. Я думал о тестировании, но я не совсем уверен, как это сделать.

Это мой первый пост на stackoverflow, хотя я очень часто получаю пользу от сайта!

Спасибо!

Вот то, о чем я говорю для индивидуальной отправки множества массивов символов. Альтернатива будет объединять все эти массивы символов в один массив символов и отправлять их.

int main() {
    sockaddr_in address;
    int server_handle;
    int addrlen = sizeof(address);
    if ((server_handle = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    {
        perror("cannot create socket");  
        exit(0);
    }
    memset((char *) &address, 0, sizeof(address)); 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = htonl(INADDR_ANY); 
    address.sin_port = htons(PORT); 
    if (bind(server_handle, (sockaddr *) &address, (socklen_t) addrlen) < 0) 
    { 
        perror("bind failed"); 
        exit(0); 
    }

    if (listen(server_handle, 3) < 0) 
    { 
        perror("In listen");  
        exit(EXIT_FAILURE); 
    } 
    while(1) {
        std::cout << "\n+++++++ Waiting for new connection ++++++++\n\n"; 
        int client_handle;
        if ((client_handle = accept(server_handle, (struct sockaddr *)&address, (socklen_t *) &addrlen))<0)
        { 
            perror("In accept");            
            exit(EXIT_FAILURE);        
        }

        // read and respond to client request 
        char buffer[30000] = {0};
        int bytesRead = read(client_handle, buffer, 30000); 

        char * httptype = "HTTP/1.1 ";
        char * status = "200 \n";
        char * contenttype = "Content-Type: text/html \n";
        char * contentlength = "Content-Length: 21\n\n";
        char * body = "<h1>hello world!</h1>";


        write(client_handle, httptype, 9);
        write(client_handle, status, 5);
        write(client_handle, contenttype, 26);
        write(client_handle, contentlength, 20);
        write(client_handle, body, 21);

        std::cout << "------------------Response sent-------------------\n";

        close(client_handle);
    }
}

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Если вы хотите отправить несколько буферов одним вызовом write, вы можете использовать векторный ввод-вывод (он же разброс / сборка ввода-вывода), поскольку руководство предлагает:

char *str0 = "hello ";
char *str1 = "world\n";
struct iovec iov[2];
ssize_t nwritten;

iov[0].iov_base = str0;
iov[0].iov_len = strlen(str0);
iov[1].iov_base = str1;
iov[1].iov_len = strlen(str1);

nwritten = writev(STDOUT_FILENO, iov, 2);
0 голосов
/ 12 марта 2019

На самом деле запись в сокет практически не отличается от записи в дескриптор файла. А функция fwrite была введена в библиотеку C по причине: write (будь то соединение TCP или файловый дескриптор) включает системный вызов в общей ОС и изменение контекста пользователя / ядра. Это изменение контекста имеет некоторые издержки, в основном, если вы пишете небольшие куски данных.

С другой стороны, если вы записываете большие куски данных с размерами, близкими к физическому размеру основного системного вызова (дисковый буфер для файлового дескриптора или максимальный размер пакета для сетевого сокета), fwrite вызовите или, в вашем примере, код, объединяющий массивы символов, на самом деле не снизит нагрузку на систему и просто добавит некоторую обработку пользовательского кода.

TL / DR: это зависит от среднего размера написанного вами. Чем оно меньше, тем выше преимущество объединения даты большими кусками перед записью. И помните: это низкоуровневая оптимизация, которую следует учитывать только в том случае, если вы определили узкое место в производительности или если код можно использовать в широко распространенной библиотеке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...