Похоже, в ZeroMQ нет смысла работать с сокетами в терминах традиционных сокетов UNIX. Я разработал архитектуру для алгоритма распределенного поиска, основанного на неправильном восприятии ZeroMQ. В моей программе есть агент, отвечающий за мониторинг других агентов и сбор их данных. Реальные данные будут передаваться между агентами по схеме PULL-PUSH или PUB-SUB. У каждого агента есть сокет PULL, который прослушивает входящие сообщения. Каждое сообщение содержит идентификационный номер, который определяет идентификацию отправителя.
На этапе инициализации монитор должен прослушивать свой сокет REP. Каждый агент подключится к известному сокету REP монитора и представится (отправит свой идентификационный номер и номер порта, который прослушивает агент). Монитор хранит все данные об агентах в записях трех полей: <ID, IP, port>
, (Вот где у меня проблема с ZMQ.) Когда определенное количество агентов становится готовым, монитор отправляет все данные (каждый агент <IP,ID,port>
) всем агентам. Последний шаг выполняется с помощью шаблона PUB-SUB между агентами и монитором.
Это изображение может помочь понять, что я хотел реализовать:
На картинке выше монитор должен разослать всем свои таблицы. Ключевой вопрос — как получить публичный IP-адрес запрашивающего (любого агента) в шаблоне REQ-REP? Все агенты привязываются к своему локальному хосту (127.0.0.1). Они должны быть распределены по произвольному номеру хоста. Так что AFAIK им нужно знать общедоступные IP друг друга.
В случае, если решения не существует, подойдет любая помощь по изменению архитектуры.
Обновить
Решение, которое я могу придумать, состоит в том, чтобы модифицировать каждого агента так, чтобы он связывался со своим публичным IP вместо localhost
, Если есть волшебный способ получения публичного IP-адреса, любой агент может отправить свой адрес на монитор.
Второе обновление
В настоящее время агент получает свой публичный IP-адрес и отправляет его через сообщение на сервер:
std::string AIT::ABT_Socket::getIP() {
std::string address = "";
FILE * fp = popen("ifconfig", "r");
if (fp) {
char *p = NULL, *e;
size_t n;
while ((getline(&p, &n, fp) > 0) && p) {
if (p = strstr(p, "inet addr:")) {
p += 10;
if (e = strchr(p, ' ')) {
*e = '\0';
return std::string(p);
address = std::string(p);
}
}
}
}
pclose(fp);
return address;
}
boost может определить ваш IP-адрес в портативном режиме следующим образом:
tcp::resolver resolver(io_service);
tcp::resolver::query query(boost::asio::ip::host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
tcp::resolver::iterator end; // End marker.
while (iter != end)
{
tcp::endpoint ep = *iter++;
std::cout << ep << std::endl;
}
Но это не значит, что это легко исправить — что, если на коробке есть несколько IP-адресов / сетевых карт / WAN / LAN и т. Д. … Когда у меня недавно была похожая ситуация, я заставил звонящего явно указать желаемый IP и порт на командной строки, а затем поделился ею при подключении к другим процессам на других хостах (в моем случае через HTTP).
Почему бы вам просто не отправить его как часть полезной нагрузки?