NS3 WiFi環(huán)境中Socket發(fā)送Packet的過程

前言

這篇文章介紹一下Socket發(fā)送Packet的過程眉尸。
NS3的socket類以及子類组去,工廠類很多男窟,調用過程復雜,琢磨了很長時間才算搞明白一點點蒿囤,本文以UDP協(xié)議為基本來說說Socket發(fā)送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<Socket> recvSink = Socket::CreateSocket (c.Get (0), tid);
      InetSocketAddress local = InetSocketAddress (Ipv4Address ("10.1.1.1"), 80);
      recvSink->Bind (local);
      recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));

      Ptr<Socket> 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);

這是個很簡單的代碼,首先安裝協(xié)議到節(jié)點容器NodeContainer對象c.
然后分配IP地址蟋软,創(chuàng)建socket對象镶摘,一個source 發(fā)送,一個recvSink 接收岳守。

Socket的創(chuàng)建過程

TypeId tid=UdpSocketFactory::GetTypeId();
Ptr<Socket> recvSink = Socket::CreateSocket (c.Get (0), tid);

這兩行代碼完成了什么功能呢凄敢?需要查看 Socket::CreateSocket方法的代碼:

Ptr<Socket> 
Socket::CreateSocket (Ptr<Node> node, TypeId tid)
{
  NS_LOG_FUNCTION (node << tid);
  Ptr<Socket> s;
  NS_ASSERT (node != 0);
  Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
  NS_ASSERT (socketFactory != 0);
  s = socketFactory->CreateSocket ();
  NS_ASSERT (s != 0);
  return s;
}

從上面的代碼可以看出,以UdpSocketFactory的TypeId創(chuàng)建一個UdpSocketFactory對象湿痢,然后利用UdpSocketFactory對象的CreateSocket ()方法創(chuàng)建一個Socket對象涝缝。

但是,我們看UdpSocketFactory的源代碼譬重,發(fā)現:

namespace ns3 {

NS_OBJECT_ENSURE_REGISTERED (UdpSocketFactory);

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

}

UdpSocketFactory非常簡單拒逮,并且是一個包含虛函數,不能創(chuàng)建對象臀规。

此時就需要回到Socket::CreateSocket方法的代碼:

Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);

這一行代碼返回的對象socketFactory 對象不是UdpSocketFactory對象滩援,應該是它的子類對象或者父類對象,但是編程思想上看塔嬉,父類對象基本不可能玩徊。只能是其子類對象。
UdpSocketFactory類的子類只有一個:UdpSocketFactoryImpl谨究。

此時再看UdpSocketFactoryImpl的CreateSocket()方法:

Ptr<Socket>
UdpSocketFactoryImpl::CreateSocket (void)
{
  NS_LOG_FUNCTION_NOARGS();
  return m_udp->CreateSocket ();
}

其中的m_udp對象是Ptr<UdpL4Protocol>恩袱,再看UdpL4Protocol的CreateSocket ():

Ptr<Socket>
UdpL4Protocol::CreateSocket (void)
{
  NS_LOG_FUNCTION_NOARGS ();
  Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
  socket->SetNode (m_node);
  socket->SetUdp (this);
  m_sockets.push_back (socket);
  return socket;
}

看到這個代碼就知道了,UdpSocketFactory的實現類UdpSocketFactoryImpl利用UdpL4Protocol對象來創(chuàng)建Socket對象胶哲。而UdpL4Protocol對象的CreateSocket 方法通過創(chuàng)建UdpSocket的實現類UdpSocketImpl來創(chuàng)建socket畔塔,并返回。

也就是說,最終創(chuàng)建的socket對象是UdpSocketImpl類型的澈吨。

節(jié)點獲取SocketFactory

看到這里把敢,node->GetObject<SocketFactory> (tid)代碼如何獲取得到SocketFactory的呢?
可以通過我的另一篇文章: NS3 Node聚合對象說明
這個文章里面說明了節(jié)點如何與其他對象之間進行聚合的棚辽。

Packet發(fā)送過程

在客戶端代碼中有一行代碼:

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

這個代碼是給源socket綁定發(fā)送packet的方法技竟。

source->GetNode ()->GetId ()是context。
Seconds (startSec)表示經過這個時間之后屈藐,調用GenerateTraffic方法榔组。

source, PpacketSize, numPackets, interPacketInterval表示調用GenerateTraffic方法的參數。

GenerateTraffic方法:

/**
 * 發(fā)送分組回調方法
 */
static void GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize,
                             uint32_t pktCount, Time pktInterval )
{
  NS_LOG_FUNCTION(socket<<pktSize<<pktCount<<pktInterval);
  if (pktCount > 0)
    {
      startTime=Simulator::Now();
      NS_LOG_LOGIC("start time:"<<startTime);
      socket->Send (Create<Packet> (pktSize));
      Simulator::Schedule (pktInterval, &GenerateTraffic,
                           socket, pktSize,pktCount-1, pktInterval);
    }
  else
    {
      socket->Close ();
    }
}

方法很簡單联逻,調用Socket對象的send方法發(fā)送packet對象搓扯。

以上便是socket從創(chuàng)建到發(fā)送packet的過程的簡單說明。

Socket通信過程

以上內容說明的是socket對象創(chuàng)建到發(fā)送packet的過程包归。
但是可能仍然有不明白socket為什么那樣寫代碼锨推?可能有點不清楚的。

TCP握手與socket通信細節(jié)
這篇文章說明了socket通信的過程公壤。

看懂了上面的文章换可,自然會對文章開始部分給出的客戶端代碼有一個更清晰的認識。

  /*
    安裝協(xié)議
  */
      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();
      /*
       創(chuàng)建socket對象厦幅,作為服務端
     */
      Ptr<Socket> recvSink = Socket::CreateSocket (c.Get (0), tid);
      InetSocketAddress local = InetSocketAddress (Ipv4Address ("10.1.1.1"), 80);
      recvSink->Bind (local);//綁定地址沾鳄,等待連接
      recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));//設置回調函數地址

      /*
       創(chuàng)建socket對象,作為客戶端
     */
      Ptr<Socket> 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);//發(fā)起連接
      //連接成功确憨,通過GenerateTraffic方法發(fā)送packet译荞。
      Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
                                      Seconds (startSec), &GenerateTraffic,
                                      source, PpacketSize, numPackets, interPacketInterval);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市休弃,隨后出現的幾起案子吞歼,更是在濱河造成了極大的恐慌,老刑警劉巖塔猾,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篙骡,死亡現場離奇詭異,居然都是意外死亡丈甸,警方通過查閱死者的電腦和手機医增,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來老虫,“玉大人,你說我怎么就攤上這事茫多∑沓祝” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夺欲。 經常有香客問我跪帝,道長,這世上最難降的妖魔是什么些阅? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任伞剑,我火速辦了婚禮,結果婚禮上市埋,老公的妹妹穿的比我還像新娘黎泣。我一直安慰自己,他們只是感情好缤谎,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布抒倚。 她就那樣靜靜地躺著,像睡著了一般坷澡。 火紅的嫁衣襯著肌膚如雪托呕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天频敛,我揣著相機與錄音裕坊,去河邊找鬼。 笑死兄纺,一個胖子當著我的面吹牛宿刮,可吹牛的內容都是我干的。 我是一名探鬼主播汁展,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼鹊碍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了食绿?” 一聲冷哼從身側響起侈咕,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎器紧,沒想到半個月后耀销,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡铲汪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年熊尉,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掌腰。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡狰住,死狀恐怖,靈堂內的尸體忽然破棺而出齿梁,到底是詐尸還是另有隱情催植,我是刑警寧澤肮蛹,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站创南,受9級特大地震影響伦忠,放射性物質發(fā)生泄漏。R本人自食惡果不足惜稿辙,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一昆码、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邻储,春花似錦赋咽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萌壳,卻和暖如春亦镶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袱瓮。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工缤骨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尺借。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓绊起,卻偏偏與公主長得像,于是被迫代替她去往敵國和親燎斩。 傳聞我的和親對象是個殘疾皇子虱歪,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容