С резьбой Erlang C-Node (cnode) Совместимость как? - PullRequest
3 голосов
/ 25 марта 2010

Я нахожусь в стадии разработки на Erlang, где мне нужно создать C-узел (см. ссылка для документов C-узла). Базовая реализация достаточно проста, однако в документе есть огромная дыра.

Код реализует однопоточный клиент и сервер. Игнорирование клиента на данный момент ... Код 'c', который реализует сервер, является однопоточным и может подключаться только к одному клиенту erlang одновременно.

  1. Запустить EPMD ('epmd -daemons')
  2. Запустить приложение сервера ('cserver 1234')
  3. Запустить клиентское приложение erlang ('erl -sname e1 -setcookie secretcookie') [в другом окне из # 2]
  4. выполнить команду сервера ('complex3: foo (3).') Из оболочки erlang в # 3

Теперь, когда сервер работает и текущая оболочка erlang подключена к серверу, попробуйте снова из другого окна.

  1. открыть новое окно.
  2. запустить клиент erlang ('erl -sname e2 -setcookie secretcookie').
  3. выполнить новую серверную команду ('complex3: foo (3).').

Обратите внимание, что система кажется зависшей ... когда она должна была выполнить команду. Причина, по которой он завис, заключается в том, что другой узел erlang подключен и другие потоки не прослушивают соединения.

ПРИМЕЧАНИЕ: Кажется, есть ошибка в обработке соединения. Я добавил тайм-аут в блоке приема и обнаружил какое-то ошибочное поведение, но не получил их всех. Кроме того, мне удалось вызвать сбой сервера cserver без предупреждений или ошибок, если я принудительно завершил работу первого узла erlang после выполнения указанных шагов.

Итак, вопрос ... Каков наилучший способ реализации C-узла с резьбой? Что такое разумное количество соединений?

1 Ответ

3 голосов
/ 18 января 2011

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

Вызов erl_accept - это то, что принимает входящие соединения.

if ((fd = erl_accept(listen, &conn)) == ERL_ERROR)
  erl_err_quit("erl_accept");
fprintf(stderr, "Connected to %s\n\r", conn.nodename);
while (loop) {
  got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);

Обратите внимание, что при таком написании cnode примет только одно соединение, а затем передаст дескриптор в цикл чтения / записи. Вот почему, когда узел erlang закрывается, cnode завершается с ошибкой, поскольку erl_receive_msg завершится ошибкой, поскольку fd будет указывать на закрытый сокет.

Если вы хотите принять более одного входящего соединения, вам придется зациклить прием соединений и реализовать способ обработки более одного дескриптора файла. Для этого вам не нужна многопоточная программа, возможно, было бы проще (и, возможно, более эффективно) использовать системный вызов poll или select, если ваша ОС их поддерживает.

Что касается оптимального количества соединений, я не думаю, что для этого есть какое-либо правило, вам нужно будет сравнить свое приложение, если вы хотите поддерживать высокий параллелизм в cnode. Но в этом случае, вероятно, было бы лучше перестроить систему так, чтобы erlang справился с параллелизмом, избавив от этого узел.

...