Intereting Posts
Ошибка при попытке отправить электронную почту через Gmail с помощью SwiftMailer вставить дочерние комментарии родительского сообщения vue js Преобразование URL-адресов из текста в ссылки, даже если протокол отсутствует PHP mysqli вставить дату из строки 301 Перенаправление со старого URL не работает (prestashop) Невозможно обновить или удалить динамически с помощью twig и php oop Определение качества изображения JPEG Загрузка файлов в IE6 Отказ от системы входа в систему PHP Как я могу отправить несколько элементов через кнопку «Купить сейчас» в Paypal PHP: Может ли CURL следовать мета-перенаправлению? Как определить, нужно ли применять utf8 декодировать или кодировать строку? Как я могу подключиться к MySQL на сервере WAMP? Symfony на Xampp очень медленно развивается, что я могу сделать? MySQL – получение таблицы HTML из базы данных – обратная косая черта перед символом котировки

Как IPC между клиентами PHP и сервером C Daemon?

и спасибо, что посмотрели на вопрос.

Фон
У меня есть несколько машин, которые непрерывно генерируют несколько (до 300) скриптов в PHP за очень короткий промежуток времени. Эти скрипты выполняются быстро (менее секунды), а затем выходят. Все эти сценарии требуют доступа только для чтения к большой структуре trie, которая будет очень дорого загружаться в память каждый раз, когда запускается каждый из сценариев. Сервер работает под управлением Linux.

Мое решение
Создайте C-демона, который сохраняет структуру trie в памяти и получает запросы от клиентов PHP. Он получит запрос от каждого из клиентов PHP, выполнит поиск по структуре памяти и ответит на ответ, сохранив скрипты PHP от выполнения этой работы. Оба запроса и ответы – короткие строки (не более 20 символов)

Моя проблема
Я очень новичок в C-демонах и межпроцессном общении. После долгих исследований я сузил выбор до «Очередей сообщений» и сокетов домена Unix. Очереди сообщений кажутся адекватными, потому что я думаю (возможно, ошибаюсь), что они ставят в очередь все запросы к демону, чтобы они отвечали последовательно. Однако сокеты домена Unix кажутся более простыми в использовании. Тем не менее, у меня есть различные вопросы, на которые я не смог найти ответы:

  1. Как скрипт PHP может отправлять и получать сообщения или использовать сокет UNIX для связи с демоном? И наоборот, как демона C отслеживает, на какой процесс PHP он должен отправить ответ?
  2. Большинство примеров демонов, которые я видел, используют бесконечный цикл while с условием сна. Моему демону необходимо обслуживать множество подключений, которые могут появиться в любое время, а задержка ответа имеет решающее значение. Как бы реагировал демон, если PHP-скрипт отправляет запрос во время сна? Я читал о опросе и epoll, будет ли это правильным способом дождаться получения сообщения?
  3. Каждый процесс PHP всегда будет отправлять один запрос, а затем будет ждать ответа. Мне нужно убедиться, что если демон недоступен / недоступен, процесс PHP будет ожидать ответа на заданное максимальное время, и если ответ не будет получен, он продолжит независимо, вместо того, чтобы висит. Это можно сделать?

Фактический поиск структуры данных очень быстрый, мне не нужно сложное многопоточное или подобное решение, так как я считаю, что обработка запросов в режиме FIFO будет достаточно. Мне также нужно, чтобы это было просто глупо, поскольку это критически важная услуга, и я довольно новичок в этом типе программы. (Я знаю, но у меня действительно нет никакого способа обойти это, и опыт обучения будет большим)

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

Спасибо за вашу помощь!


Обновить

Зная гораздо больше, чем когда-либо, когда я задавал этот вопрос, я просто хотел указать всем, кто заинтересован в том, что и инфраструктура Thrift, и ZeroMQ делают фантастическую работу по абстрагированию от жесткого программирования на уровне сокета. Thrift даже дает вам леса для сервера бесплатно!

На самом деле, вместо того, чтобы идти на все тяжелые работы по созданию сетевого сервера, подумайте о написании кода сервера приложений с помощью хорошего асинхронного сервера, который уже решил проблему для вас. Конечно, серверы, использующие асинхронный ввод-вывод, отлично подходят для сетевых приложений, которые не требуют интенсивной обработки процессора (или блоков цикла событий).

Примеры для python: Twisted , gevent . Я предпочитаю gevent, и я не включаю торнадо, потому что он сосредоточен на стороне сервера HTTP.

Примеры для Ruby: EventMachine

Конечно, Node.js в основном является выбором по умолчанию для асинхронного сервера в настоящее время.

Если вы хотите углубиться, прочитайте C10k Problem и Unix Network Programing .

Solutions Collecting From Web of "Как IPC между клиентами PHP и сервером C Daemon?"

Я подозреваю, что Thrift – это то, что вы хотите. Вам нужно написать небольшой код для создания PHP <-thrift-> C ++ <-> C, но это, вероятно, будет более надежным, чем ваш собственный.

Вы также можете загрузить структуру данных в общую память с помощью функций общей памяти PHP http://www.php.net/manual/en/book.shmop.php .

О, это не очевидно из документации, но координационная переменная – $ key в shmop_open. Каждый процесс, требующий доступа к общей памяти, должен иметь тот же ключ $. Таким образом, один процесс создает разделяемую память с помощью ключа $. Другие процессы затем могут получить доступ к этой общей памяти, если они используют один и тот же ключ $. Я считаю, что вы можете выбрать все, что угодно, для $ key.

«Проблема» (может быть, нет?) Заключается в том, что в MysSys MQ наверняка будет много потребителей / производителей. Хотя вполне возможно, что вы делаете, если у вас нет необходимости в m: n для модели производителя: потребитель к ресурсам, здесь у вас есть модель запроса / ответа.

Вы можете получить некоторые странные зависания с SysV MQ, как есть.

Во-первых, вы уверены, что гнезда INET для вас недостаточно быстры? Быстрый пример PHP с использованием сокетов домена unix находится по адресу http://us.php.net/socket-create-pair (как пример кода, конечно, используйте socket_create () для конечной точки PHP).

Хотя я никогда не пробовал это, memcached вместе с соответствующим расширением PHP должен устранить большую часть работы ворчания.

Уточнение: я неявно предполагал, что если вы это сделаете, вы поместите отдельные листья три в memcache, используя сплющенные ключи, отбрасывая trie. Возможность и желательность этого подхода, конечно, зависит от многих факторов, в первую очередь от источника данных.

IPC между сценарием можно легко сделать с помощью Pipes. Это делает очень простую реализацию.

Вот рабочий пример, где php-скрипт отправляет запрос на C-демон и затем ждет ответа. Он использует сокеты домена Unix в режиме датаграммы, поэтому он быстрый и простой.

client.php

<?php do { $file = sys_get_temp_dir() . '/' . uniqid('client', true) . '.sock'; } while (file_exists($file)); $socket = socket_create(AF_UNIX, SOCK_DGRAM, 0); if (socket_bind($socket, $file) === false) { echo "bind failed"; } socket_sendto($socket, "Hello World!", 12, 0, "/tmp/myserver.sock", 0); if (socket_recvfrom($socket, $buf, 64 * 1024, 0, $source) === false) { echo "recv_from failed"; } echo "received: [" . $buf . "] from: [" . $source . "]\n"; socket_close($socket); unlink($file); ?> 

server.c

 #include <stdio.h> #include <sys/un.h> #include <sys/socket.h> #define SOCKET_FILE "/tmp/myserver.sock" #define BUF_SIZE 64 * 1024 int main() { struct sockaddr_un server_address = {AF_UNIX, SOCKET_FILE}; int sock = socket(AF_UNIX, SOCK_DGRAM, 0); if (sock <= 0) { perror("socket creation failed"); return 1; } unlink(SOCKET_FILE); if (bind(sock, (const struct sockaddr *) &server_address, sizeof(server_address)) < 0) { perror("bind failed"); close(sock); return 1; } while (1) { struct sockaddr_un client_address; int i, numBytes, len = sizeof(struct sockaddr_un); char buf[BUF_SIZE]; numBytes = recvfrom(sock, buf, BUF_SIZE, 0, (struct sockaddr *) &client_address, &len); if (numBytes == -1) { puts("recvfrom failed"); return 1; } printf("Server received %d bytes from %s\n", numBytes, client_address.sun_path); for (i = 0; i < numBytes; i++) buf[i] = toupper((unsigned char) buf[i]); if (sendto(sock, buf, numBytes, 0, (struct sockaddr *) &client_address, len) != numBytes) puts("sendto failed"); } } 

nanomsg закодирован в простой C, поэтому я думаю, что он лучше подходит для ваших нужд, чем Thrift и ZeroMQ, которые закодированы на C ++.

Он имеет обертки для многих языков, включая PHP.

Ниже приведен рабочий пример с использованием протокола NN_PAIR : (вы также можете использовать NN_REQREP )

client.php

 <?php $sock = new Nanomsg(NanoMsg::AF_SP, NanoMsg::NN_PAIR); $sock->connect('ipc:///tmp/myserver.ipc'); $sock->send('Hello World!', 0); $sock->setOption(NanoMsg::NN_SOL_SOCKET, NanoMsg::NN_RCVTIMEO, 1000); $data = $sock->recv(0, 0); echo "received: " . $data . "\n"; ?> 

server.c

 #include <stdio.h> #include <string.h> #include <nanomsg/nn.h> #include <nanomsg/pair.h> #define address "ipc:///tmp/myserver.ipc" int main() { unsigned char *buf = NULL; int result; int sock = nn_socket(AF_SP, NN_PAIR); if (sock < 0) puts("nn_socket failed"); if (nn_bind(sock, address) < 0) puts("bind failed"); while ((result = nn_recv(sock, &buf, NN_MSG, 0)) > 0) { int i, size = strlen(buf) + 1; // includes null terminator printf("RECEIVED \"%s\"\n", buf); for (i = 0; buf[i] != 0; i++) buf[i] = toupper(buf[i]); nn_send(sock, buf, size, 0); nn_freemsg(buf); } nn_shutdown(sock, 0); return result; }