Один сервер и несколько клиентов в NS-3 - PullRequest
0 голосов
/ 07 января 2020

Я хочу смоделировать сервер, который получает пакеты от нескольких клиентов и обрабатывает данные этих пакетов одновременно в NS-3. Я симулировал один сервер и клиент в NS-3, изменив приложения udp-echo-server и udp-echo-client в NS-3. Теперь для реализации нескольких клиентов я изменил конечные строки функции StartApplication в приложении udp-echo-server следующим образом:


    if((childpid=fork())==0)
    {
       m_socket->SetRecvCallback (MakeCallback(&UdpEchoServer::HandleRead, this));
       m_socket6->SetRecvCallback (MakeCallback(&UdpEchoServer::HandleRead, this));
    }

Но это не работает. На самом деле, соединяя два клиента, он просто читает первый клиент и игнорирует второго клиента. Он просто запускает функцию StartApplication один раз. Кто-нибудь может мне помочь с этим?

Спасибо

1 Ответ

0 голосов
/ 11 марта 2020

Основная проблема с тем, что вы пытаетесь сделать, заключается в том, что ns-3 - это однопоточный симулятор. Вы не должны использовать fork to имитацию разветвления. Если вам нужно несколько клиентов, вы должны явно их создать. Я быстро привел простой пример:

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

// simple udp multi-client, single-server simulation to answer 
// https://stackoverflow.com/q/59632211/13040392

#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-grid.h"
#include "ns3/flow-monitor-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("UdpMultiClient");

int
main(int argc, char *argv[]) {
    // create grid structure of network
    // not necessary. Could just create topology manually
    PointToPointHelper p2pLink;
    PointToPointGridHelper grid (2, 2, p2pLink);
    InternetStackHelper stack;
    grid.InstallStack(stack);

    // assign IP addresses to NetDevices
    grid.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"),
                              Ipv4AddressHelper ("10.2.1.0", "255.255.255.0"));
    Ipv4GlobalRoutingHelper::PopulateRoutingTables();

    // configure and install server app
    int serverPort = 8080;
    UdpEchoServerHelper serverApp (serverPort);
    serverApp.Install(grid.GetNode(0,0));
    Address serverAddress = InetSocketAddress(grid.GetIpv4Address(0,0), serverPort);

    // configure and install client apps
    UdpEchoClientHelper clientApp (serverAddress);
    clientApp.Install(grid.GetNode(0,1));
    clientApp.Install(grid.GetNode(1,0));
    clientApp.Install(grid.GetNode(1,1));

    // install FlowMonitor to collect simulation statistics
    FlowMonitorHelper flowHelper;
    Ptr<FlowMonitor> flowMonitor = flowHelper.InstallAll();

    // configure and run simulation
    Simulator::Stop(Seconds(10));
    NS_LOG_UNCOND("Starting simulation.");
    Simulator::Run();
    Simulator::Destroy();
    NS_LOG_UNCOND("Simulation completed.");

    // simulation complete
    // get statistics of simlation from FlowMonitor
    flowMonitor->CheckForLostPackets();
    std::map<FlowId, FlowMonitor::FlowStats> stats = flowMonitor->GetFlowStats();
    uint64_t txPacketsum = 0;
    uint64_t rxPacketsum = 0;
    uint64_t DropPacketsum = 0;
    uint64_t LostPacketsum = 0;
    double Delaysum = 0;
    for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin(); i != stats.end(); ++i) {
        txPacketsum += i->second.txPackets;
        rxPacketsum += i->second.rxPackets;
        LostPacketsum += i->second.lostPackets;
        DropPacketsum += i->second.packetsDropped.size();
        Delaysum += i->second.delaySum.GetSeconds();
    }
    NS_LOG_UNCOND(std::endl << "  SIMULATION STATISTICS");
    NS_LOG_UNCOND("  All Tx Packets: " << txPacketsum);
    NS_LOG_UNCOND("  All Rx Packets: " << rxPacketsum);
    NS_LOG_UNCOND("  All Delay: " << Delaysum / txPacketsum);
    NS_LOG_UNCOND("  All Lost Packets: " << LostPacketsum);
    NS_LOG_UNCOND("  All Drop Packets: " << DropPacketsum);
    NS_LOG_UNCOND("  Packets Delivery Ratio: " << ((rxPacketsum * 100) / txPacketsum) << "%");
    NS_LOG_UNCOND("  Packets Lost Ratio: " << ((LostPacketsum * 100) / txPacketsum) << "%");
    // flowMonitor->SerializeToXmlFile("test.xml", true, true);

    return 0;
}

В качестве краткого примечания, в

UdpEchoClientHelper clientApp (serverAddress);
clientApp.Install(grid.GetNode(0,1));
clientApp.Install(grid.GetNode(1,0));
clientApp.Install(grid.GetNode(1,1));

мы установили UdpEchoClient на три Nodes. Согласно документации для этого Application, UdpEchoClient отправляет пакет каждые 1000000000 нс = 1 с по умолчанию. Поскольку мы установили продолжительность симуляции на 10 секунд, используя Simulator::Stop(Seconds(10));, мы ожидаем, что каждый клиент отправит 10 пакетов на сервер. Таким образом, в общей сложности 30 пакетов должны быть отправлены клиентами. Кроме того, поскольку мы используем UdpEchoServerHelper на сервере, каждый пакет будет возвращаться сервером обратно. Поэтому в сети должно быть передано в общей сложности 30 x 2 = 60 пакетов.

Вывод сценария

Starting simulation.
Simulation completed.

  SIMULATION STATISTICS
  All Tx Packets: 60
  All Rx Packets: 60
  All Delay: 0.0423177
  All Lost Packets: 0
  All Drop Packets: 0
  Packets Delivery Ratio: 100%
  Packets Lost Ratio: 0%

Этот ответ на самом деле демонстрирует несколько особенностей ns-3, поэтому не стесняйтесь задавать любые дополнительные вопросы. Я настоятельно рекомендую вам ознакомиться с документацией ns-3 для классов, с которыми вы еще не сталкивались.

...