NS 3 WiFi環境でSocketがPacketを送信するプロセス

6769 ワード

前言
この記事では、SocketがPacketを送信する過程を紹介します.NS 3のsocketクラスおよびサブクラスは,ファクトリクラスが多く,呼び出しプロセスが複雑で,長い間考えてやっと少し理解できたが,本稿ではUDPプロトコルを基本としてSocketがPacketを送信するプロセスについて述べる.
クライアントコード
      InternetStackHelper internet;
      internet.SetIpv6StackInstall(false);
      internet.Install (c);

      Ipv4AddressHelper ipv4;
      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
      Ipv4InterfaceContainer i = ipv4.Assign (devices);

      TypeId tid=UdpSocketFactory::GetTypeId();

      Ptr recvSink = Socket::CreateSocket (c.Get (0), tid);
      InetSocketAddress local = InetSocketAddress (Ipv4Address ("10.1.1.1"), 80);
      recvSink->Bind (local);
      recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));

      Ptr source = Socket::CreateSocket (c.Get (1), tid);
      InetSocketAddress remote = InetSocketAddress (Ipv4Address ("10.1.1.2"), 80);
      source->SetAllowBroadcast (false);
      source->Bind(remote);
      source->Connect (local);

      Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
                                      Seconds (startSec), &GenerateTraffic,
                                      source, PpacketSize, numPackets, interPacketInterval);

これは簡単なコードで、まずプロトコルをノードコンテナNodeContainerオブジェクトcにインストールし、IPアドレスを割り当て、socketオブジェクトを作成し、source送信、recvSink受信を行う.
Socketの作成プロセス
TypeId tid=UdpSocketFactory::GetTypeId();
Ptr recvSink = Socket::CreateSocket (c.Get (0), tid);

この2行のコードはどんな機能を完成しましたか?Socket::CreateSocketメソッドのコードを表示する必要があります.
Ptr 
Socket::CreateSocket (Ptr node, TypeId tid)
{
  NS_LOG_FUNCTION (node << tid);
  Ptr s;
  NS_ASSERT (node != 0);
  Ptr socketFactory = node->GetObject (tid);
  NS_ASSERT (socketFactory != 0);
  s = socketFactory->CreateSocket ();
  NS_ASSERT (s != 0);
  return s;
}

上記のコードから分かるように、UdpSocketFactoryのType IdでUdpSocketFactoryオブジェクトを作成し、UdpSocketFactoryオブジェクトのCreateSocket()メソッドでSocketオブジェクトを作成します.
しかし、UdpSocketFactoryのソースコードを見てみると、
namespace ns3 {

NS_OBJECT_ENSURE_REGISTERED (UdpSocketFactory);

TypeId UdpSocketFactory::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::UdpSocketFactory")
    .SetParent ()
    .SetGroupName ("Internet")
  ;
  return tid;
}

}

UdpSocketFactoryは非常に簡単で、オブジェクトを作成できない虚関数を含むものです.
Socket::CreateSocketメソッドのコードに戻る必要があります.
Ptr socketFactory = node->GetObject (tid);

この行のコードが返すオブジェクトsocketFactoryオブジェクトはUdpSocketFactoryオブジェクトではなく、そのサブクラスオブジェクトまたは親オブジェクトであるべきですが、プログラミングの思想的には親オブジェクトは基本的に不可能です.サブクラスオブジェクトのみです.UdpSocketFactoryクラスのサブクラスは1つのみ:UdpSocketFactoryImpl.
次にUdpSocketFactoryImplのCreateSocket()メソッドを見てみましょう.
Ptr
UdpSocketFactoryImpl::CreateSocket (void)
{
  NS_LOG_FUNCTION_NOARGS();
  return m_udp->CreateSocket ();
}

その中のm_udpオブジェクトはPtrで、UdpL 4 ProtocolのCreateSocket()を参照してください.
Ptr
UdpL4Protocol::CreateSocket (void)
{
  NS_LOG_FUNCTION_NOARGS ();
  Ptr socket = CreateObject ();
  socket->SetNode (m_node);
  socket->SetUdp (this);
  m_sockets.push_back (socket);
  return socket;
}

このコードを見て分かるように、UdpSocketFactoryの実装クラスUdpSocketFactoryImplは、UdpL 4 Protocolオブジェクトを使用してSocketオブジェクトを作成します.一方、UdpL 4 ProtocolオブジェクトのCreateSocketメソッドは、UdpSocketのインプリメンテーションクラスUdpSocketImplを作成してsocketを作成し、返します.
すなわち,最終的に作成されるsocketオブジェクトはUdpSocketImplタイプである.
ノード取得SocketFactory
ここでnode->GetObject(tid)コードはどのようにしてSocketFactoryを取得しますか?この記事では、ノードが他のオブジェクトとどのように集約されているかを説明します.
Packet送信プロセス
クライアント・コードの行:
Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
                                      Seconds (startSec), &GenerateTraffic,
                                      source, PpacketSize, numPackets, interPacketInterval);

このコードはソースsocketバインドにpacketを送信する方法です.
source->GetNode()->GetId()はcontextです.Seconds(startSec)は、この時間が経過した後にGenerateTrafficメソッドが呼び出されることを示す.
SOurce,PpacketSize,numPackets,interPacketIntervalはGenerateTrafficメソッドを呼び出すパラメータを表す.
GenerateTrafficメソッド:
/**
 *         
 */
static void GenerateTraffic (Ptr socket, uint32_t pktSize,
                             uint32_t pktCount, Time pktInterval )
{
  NS_LOG_FUNCTION(socket< 0)
    {
      startTime=Simulator::Now();
      NS_LOG_LOGIC("start time:"<Send (Create (pktSize));
      Simulator::Schedule (pktInterval, &GenerateTraffic,
                           socket, pktSize,pktCount-1, pktInterval);
    }
  else
    {
      socket->Close ();
    }
}

メソッドは簡単で、Socketオブジェクトのsendメソッドを呼び出してpacketオブジェクトを送信します.
以上、socketの作成からpacketの送信までの手順の簡単な説明です.
Socket通信プロセス
以上、socketオブジェクトがpacketを送信するために作成されるプロセスについて説明します.しかし、socketがなぜコードを書いたのか分からないかもしれません.ちょっとわからないかもしれません.
TCP握手とsocket通信の詳細この文章はsocket通信の過程を説明した.
上記の文章を読むと、文章の開始部分に与えられたクライアントコードをより明確に認識することができます.
  /*
        
  */
      InternetStackHelper internet;
      internet.SetIpv6StackInstall(false);
      internet.Install (c);


    /*
        IP  
     */
      Ipv4AddressHelper ipv4;
      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
      Ipv4InterfaceContainer i = ipv4.Assign (devices);

      TypeId tid=UdpSocketFactory::GetTypeId();
      /*
         socket  ,     
     */
      Ptr recvSink = Socket::CreateSocket (c.Get (0), tid);
      InetSocketAddress local = InetSocketAddress (Ipv4Address ("10.1.1.1"), 80);
      recvSink->Bind (local);//    ,    
      recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));//        

      /*
         socket  ,     
     */
      Ptr source = Socket::CreateSocket (c.Get (1), tid);
      InetSocketAddress remote = InetSocketAddress (Ipv4Address ("10.1.1.2"), 80);
      source->SetAllowBroadcast (false);
      source->Bind(remote);//    
      source->Connect (local);//    
      //    ,  GenerateTraffic    packet。
      Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
                                      Seconds (startSec), &GenerateTraffic,
                                      source, PpacketSize, numPackets, interPacketInterval);