#c #multithreading #sockets #unix
#c #многопоточность #розетки #unix
Вопрос:
Я пытаюсь создать простой HTTP — сервер на C . Я хочу, чтобы каждый запрос обрабатывался одновременно в отдельных потоках, но когда я создаю поток и ставлю простой sleep(10)
в начале, чтобы вызвать некоторую задержку, другой запрос к серверу не может быть выполнен до завершения первого потока. Что я делаю не так?
Вот мой код до сих пор:
#include lt;unistd.hgt; #include lt;stdio.hgt; #include lt;sys/socket.hgt; #include lt;stdlib.hgt; #include lt;netinet/in.hgt; #include lt;stringgt; #include lt;ostreamgt; #include lt;iostreamgt; #include lt;threadgt; using namespace std; void send_response (int socket) { sleep (10); char buffer[2048] = {0}; int request = recv (socket, buffer, 2048, 0); if (request == -1) { perror ("error"); } string message = "Hello from server"; string length = to_string (message.length ()); string hello = "HTTP/1.1 200 OKnContent-Type: text/plainnContent-Length: " length "nn" message; send (socket, hello.c_str (), hello.length (), 0); close (socket); } int main(int argc, char const *argv[]) { struct sockaddr_in address; int opt = 1; socklen_t addrlen = sizeof (address); int server_fd = socket (AF_INET, SOCK_STREAM, 0); if (server_fd == 0) { perror ("socket failed"); exit (EXIT_FAILURE); } if (setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, amp;opt, sizeof (opt))) { perror ("setsockopt"); exit (EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons (8080); if (bind (server_fd, (struct sockaddr *)(amp;address), sizeof (address)) lt; 0) { perror ("bind failed"); exit (EXIT_FAILURE); } if (listen (server_fd, 3) lt; 0) { perror ("listen"); exit (EXIT_FAILURE); } while (true) { int new_socket = accept (server_fd, (struct sockaddr *)(amp;address), amp;addrlen); if (new_socket lt; 0) { perror ("accept"); exit (EXIT_FAILURE); } thread response (amp;send_response, new_socket); response.detach (); cout lt;lt; "request handled" lt;lt; endl; } return 0; }
Мне не нужно ждать завершения потока или получать какие-либо данные из потока, я просто хочу, чтобы он запустился, выполнил некоторую работу и отправил что-то обратно клиенту. Я ожидаю, что каждый поток будет выполнять приличный объем работы, поэтому я использовал sleep.
Изменить: Похоже, что цикл готов и ожидает второго подключения и успешно примет новое соединение и создаст новый поток для его обработки, но только если второе соединение с другого IP-адреса. Поэтому, если я зайду на сервер по адресу 127.0.0.1:8080 и с другого локального IP-адреса, например 192.168.1.91, оба соединения будут выполняться двумя потоками одновременно. Однако, если я просто открою две вкладки, обе в 127.0.0.1:8080, одновременно будет приниматься только одно соединение, другое остановится. Похоже, мне нужен код для обработки нескольких подключений с одного и того же IP-адреса, но поиск такого рода проблем в Google не дал мне никаких хороших результатов.
Комментарии:
1. Я ожидаю, что каждый поток будет выполнять приличный объем работы, вот почему я использовал sleep , что вы имеете в виду?
2. Я думаю, что проблема заключается в области объекта потока — он находится внутри цикла while. Таким образом, после одной итерации объект выходит за пределы области видимости.
3. Я имею в виду, что завершение каждого потока займет несколько секунд, и я бы предпочел, чтобы клиенты не ждали только потому, что одно ядро в системе 12 занято обработкой одного запроса.
4. Вы правы, функцию не нужно передавать по адресу. Я сделал это, потому что в документации говорится, что первый параметр-это «указатель на функцию, указатель на элемент или любой вид объекта функции, который можно перемещать», поэтому я передал адрес. Однако это не имеет значения для того, работает код или нет.
5. Можете ли вы подключить отладчик и прервать работу, пока висит второй запрос? Это должно рассказать вам, чем занимается основная тема.
Ответ №1:
Ладно, моя вина, все работает так, как ожидалось. Использование wget
для отправки нескольких запросов с одного и того же IP-адреса приводит к созданию нескольких потоков и одновременной обработке запросов. В Chrome по какой-то причине открытие нескольких вкладок с одного и того же IP-адреса приводит к их последовательной отправке, но в Firefox они отправляются параллельно, поступают и обрабатываются одновременно. Это странно, но я добавлю в него странности Хрома.