[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The native sockets API for ns-3 provides an interface to various types of transport protocols (TCP, UDP) as well as to packet sockets and, in the future, Netlink-like sockets. However, users are cautioned to understand that the semantics are not the exact same as one finds in a real system (for an API which is very much aligned to real systems, see the next section).
class ns3::Socket
is defined in src/node/socket.cc,h
.
Readers will note that many public member functions are aligned
with real sockets function calls, and all other things being equal,
we have tried to align with a Posix sockets API. However, note that:
ns3::Packet
class to transfer data
between application and socket. This may seem a little funny to
people to pass "Packets" across a stream socket API, but think
of these packets as just fancy byte buffers at this level (more
on this also below).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Figure 6.1: Implementation overview of native sockets API
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An application that wants to use sockets must first create one. On real systems, this is accomplished by calling socket():
int socket(int domain, int type, int protocol);
which creates a socket in the system and returns an integer descriptor.
In ns-3, we have no equivalent of a system call at the lower layers, so we adopt the following model. There are certain factory objects that can create sockets. Each factory is capable of creating one type of socket, and if sockets of a particular type are able to be created on a given node, then a factory that can create such sockets must be aggregated to the Node.
static Ptr<Socket> CreateSocket (Ptr<Node> node, TypeId tid);
Examples of TypeIds to pass to this method are TcpSocketFactory
,
PacketSocketFactory
, and UdpSocketFactory
.
This method returns a smart pointer to a Socket object. Here is an example:
Ptr<Node> n0; // Do some stuff to build up the Node's internet stack Ptr<Socket> localSocket = Socket::CreateSocket (n0, TcpSocketFactory::GetTypeId ());
In some ns-3 code, sockets will not be explicitly created by user's
main programs, if an ns-3 application does it. For instance, for
class ns3::OnOffApplication
, the function StartApplication()
performs the socket creation, and the application holds the socket
pointer.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Below is a typical sequence of socket calls for a TCP client in a real implementation:
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(sock, ...);
connect(sock, ...);
send(sock, ...);
recv(sock, ...);
close(sock);
There are analogs to all of these calls in ns-3, but we will focus on two aspects here. First, most usage of sockets in real systems requires a way to manage I/O between the application and kernel. These models include blocking sockets, signal-based I/O, and non-blocking sockets with polling. In ns-3, we make use of the callback mechanisms to support a fourth mode, which is analogous to POSIX asynchronous I/O.
In this model, on the sending side, if the send()
call were to
fail because of insufficient buffers, the application suspends the
sending of more data until a function registered at the
SetSendCallback()
callback is invoked. An application can
also ask the socket how much space is available by calling
GetTxAvailable ()
. A typical sequence of events for
sending data (ignoring connection setup) might be:
SetSendCallback (MakeCallback(&HandleSendCallback));
Send ();
Send ();
// Send fails because buffer is full
Send (); // Start sending again
Similarly, on the receive side, the socket user does not block on
a call to recv()
. Instead, the application sets a callback
with SetRecvCallback ()
in which the socket will notify the
application when (and how much) there is data to be read, and
the application then calls Recv()
to read the data until
no more can be read.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are two basic variants of Send()
and Recv()
supported:
virtual int Send (Ptr<Packet> p) = 0; int Send (const uint8_t* buf, uint32_t size); Ptr<Packet> Recv (void); int Recv (uint8_t* buf, uint32_t size);
The non-Packet variants are left for legacy API reasons. When calling
the raw buffer variant of Send()
, the buffer is immediately
written into a Packet and the Send (Ptr<Packet> p)
is invoked.
Users may find it semantically odd to pass a Packet to a stream socket
such as TCP. However, do not let the name bother you; think of
ns3::Packet
to be a fancy byte buffer. There are a few reasons why
the Packet variants are more likely to be preferred in ns-3:
uint8_t* buf
may sometimes incur an additional copy).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Sometimes, users want the simulator to just pretend that there is an
actual data payload in the packet (e.g. to calculate transmission delay)
but do not want to actually produce or consume the data. This is
straightforward to support in ns-3; have applications call
Create<Packet> (size);
instead of Create<Packet> (buffer, size);
.
Similarly, passing in a zero to the pointer argument in the raw buffer
variants has the same effect. Note that, if some subsequent code tries
to read the Packet data buffer, the fake buffer will be converted to
a real (zero'ed) buffer on the spot, and the efficiency will be lost there.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
to be completed
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
to be completed
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
to be completed
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated on September, 23 2008 using texi2html 1.76.