四种套接字以及使用实例
套接字常用的套接字有两种,包括两种: SOCK_STREAM、SOCK_DGRAM。对应的也就是常用的UDP,TCP对应套接字。
原始套接字
原始套接字也即RAW SOCKET, 该种套接字可以直接发送/接收IP协议数据包而不需要任何传输层协议。
packet套接字
该种套接字也就是SOCK_PACKET的,可以直接越过传输层和网络层在数据链路层进行报文收发。
这三种对应的关系如下:
下方为在NS3中相关socket的类及实现过程。
NS3 应用层协议
NS3 提供了很多内置应用层协议。如下图所示:
PacketSink
从上图可以看出对于接收方有着很通用的应用层协议PacketSink。该服务模型可以接收所有的下层协议的分组。包括(TCP, UDP, IPv4, IPv6, NetDevice), 该应用层通过 trace变量系统对分组的信息进行打印。
OnOffApplication
该应用层系统也很经典, 可以周期地均匀发送数据分组,该应用层协议也是应用很多的分组产生器。
Ping
该指令可以模拟 net-tools中的链路通断测试。该应用层协议也是一个很好的 RAW SOCKET使用实例。
UDP
除此之外,也可以进行自定义应用层协议,这就需要对基础的Socket使用方法进行熟悉。 例如常用的UDPhi用样例如下
Ptr<Socket> srcSocket = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::UdpSocketFactory"));
srcSocket->Bind ();
srcSocket->SetRecvCallback (MakeCallback (&srcSocketRecv));
Ptr<Socket> dstSocket = Socket::CreateSocket (nDst, TypeId::LookupByName ("ns3::UdpSocketFactory"));
uint16_t dstport = 12345;
Ipv4Address dstaddr ("10.20.1.2");
InetSocketAddress dst = InetSocketAddress (dstaddr, dstport);
dstSocket->Bind (dst);
dstSocket->SetRecvCallback (MakeCallback (&dstSocketRecv));
// 下方为各种官方提供的类以及该类的代码进行解析。
packet-socket使用
下方代码使用了OnOffApplication作为发送方代码, 并且使用了其中的PacketSocketFactory的socket模式。
NS_LOG_INFO ("Create Applications.");
// Create the OnOff application to send raw datagrams
// 首先对 socket 地址进行处理
PacketSocketAddress socket;
socket.SetSingleDevice (devs.Get (0)->GetIfIndex ());
// 指定了 device 中第二个的地址作为目标地址
socket.SetPhysicalAddress (devs.Get (1)->GetAddress ());
socket.SetProtocol (2);
// 在这里使用提供的 OnOff 应用层协议
OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
onoff.SetConstantRate (DataRate ("500kb/s"));
// 安装了该应用层协议 在 nodes[0] 之上。
ApplicationContainer apps = onoff.Install (nodes.Get (0));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
// 重新设置socket 模式, 并安装在 nodes[3] 之上
socket.SetSingleDevice (devs.Get (3)->GetIfIndex ());
socket.SetPhysicalAddress (devs.Get (0)->GetAddress ());
socket.SetProtocol (3);
onoff.SetAttribute ("Remote", AddressValue (socket));
apps = onoff.Install (nodes.Get (3));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
// Install packet sink on node 0 to receive packets from node 1
// 设置 PacketSink 的助手函数, 并安装到节点之上
PacketSinkHelper sink = PacketSinkHelper ("ns3::PacketSocketFactory",
socket);
apps = sink.Install (nodes.Get (0));
apps.Start (Seconds (0.0));
apps.Stop (Seconds (20.0));
// While the below trace sink is hooked to all nodes (the wildcard "*")
// only one packet sink (on node 0) is actually added above, so
// only the receive events on node 0 will be traced
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx",
MakeCallback (&SinkRx));
总结
总之,NS3 提供了模拟不同应用层协议的基础,并且提供了丰富的应用层协议的实现,可以参考源代码目录下的示例程序进行学习。