[Ns-developers] Students, Sockets and Smart Pointers
Gustavo Carneiro
gjcarneiro at gmail.com
Thu Mar 27 18:09:42 PDT 2008
Craig,
I might partially agree with what you say students should or should not do.
But is beside the question.
The issue here is whether or not NS 3 should 1) catch users mistakes and
print a useful error message, or 2) accommodate different programing styles
which people with different backgrounds may be used to. In the case in
question, however, NS 3 does neither of the above. In this case the
programming error just leads to a "silent failure", i.e. the packets are not
received in the destination node, but there is no hint from NS-3 of why that
happens; not even one of those cryptic assertion failures this time...
Teaching to code "correctly" is not a good solution, else why do we need
smart pointers at all? Let's get rid of Ptr<T> and "teach" programmers to
Ref and Unref.
I'm sorry, but every time I see a case like this I cannot in good conscience
simply learn from my mistake and move on, because I know many others will
probably make the same mistake and spend the same time as I did figuring out
what is wrong. A good library, where reasonable, prevents programmers from
making mistakes, even when those programmers are in a hurry to get the code
working have not had time to read the entire reference manual.
A similar rule exists for graphical user interfaces, btw. They say that a
good GUI should be intuitive enough to allow users to perform most
operations without having to even open the user manual.
On 27/03/2008, craigdo at ee.washington.edu <craigdo at ee.washington.edu> wrote:
>
> There's a discussion going on in the context of ns-3 bug 154 that I think
> deserves a wider distribution.
>
> Gustavo has reported a student who wrote some code to use sockets directly
> which I reproduce at the end of the message. [If you happen to be the
> student who wrote this code, I'm not pointing fingers at you. I'm more
> pointing fingers at the developers (me too) who led you down the path you
> found yourself in.]
>
> While there may be some issues with the semantics of socket lifetime
> management that are being addressed in the bug tracker, IMO the important
> issue uncovered here is much more fundamental.
>
> First, let me make some rather blunt observations:
>
> 1) The code in question uses low-level ns-3 APIs;
> 2) The author does not understand the ns-3 object model and especially
> what
> smart pointers do;
> 3) If you try and write low level code without understanding the object
> model, you *will* fail (if not specifically on socket-related things,
> you'll
> get bitten somewhere else).
> 4) There is deep confusion in this code about what is setup and what is
> simulation;
> 5) If you try and write a simulation without understanding what is setup
> and
> what is simulation, and how to kick start a simulation, you *will* fail.
>
> To borrow a term from phase space, we seem to have set up an attractor
> that
> led this student to a place where s/he was almost certain to fail in his
> attempt to write something that should have been very, very simple.
>
> Really, the student *should* have found his or her way into one of our
> applications via one of our samples or examples and then modified one of
> them slightly to do what he or she wanted. That is what I would have
> hoped
> would happen.
>
> However, one of the things that "everybody knows" is that when you start
> programming on an unfamiliar system, the thing to do is to look to use
> sockets. In ns-3, unfortunately, this usually reasonable approach leads
> you
> immediately down into the heart of the system where probably *everything*
> is
> unfamiliar and works in unexpected ways. This is bad. We have
> unintentionally set this person up for failure by leading him or her into
> the bowels of the system and saying, "here you go, have a nice day."
>
> I think the solution to this particular problem is not to worry about what
> part of the system holds on to references to sockets. I think it is more
> along the lines of making a simple socket helper-like thing that wraps up
> all of the ns-3-specific stuff and makes doing something conceptually
> simple
> actually simple in reality. Over the past couple of weeks we seem to have
> come to the conclusion that it is better to introduce folks slowly to our
> beautiful, elegant but hard-to-grok low-level interfaces. Our helpers are
> all simple stack-based things. This episode serves to reinforce the
> correctness of that decision.
>
> I think we need to have a simple simulation along the lines of one of the
> canonical socket-based client-server apps that gives a starting place for
> people like this student that doesn't involve having to delve so deeply
> into
> the system; doesn't involve having to learn about the object model, etc.,
> etc. We need to be much clearer about what is simply setup, and what is
> simulation and how we start things moving. This is (to me) a surprisingly
> subtle distinction for some folks.
>
> I think an answer is to create and advertize an entry-level starting point
> that probably doesn't involve anything deeper than a minimal subset of the
> upcoming helper API and something that looks and feels as close to sockets
> as is possible given our asynchronous environment. This way, people who
> are
> approaching ns-3 with the natural inclination to use sockets will be
> "attracted" to the simple straightforward answer, not the "maze of twisty
> little passages" that may be the result of finding oneself in the middle
> of
> low-level ns-3 code. They should find something that looks familiar when
> they start.
>
> If we have people that find themselves trying to program low-level ns-3
> sockets without understanding what Ptr<Socket> means, or write a
> simulation
> without understanding basics, it will certainly be a disaster.
>
> I mean, in this case, the system behaved exactly how I would have expected
> it to behave given what it was asked to do.
>
> My $.02 anyway.
>
> -- Craig
>
> ----------
> class Test
> {
> public:
>
> void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const
> Address
> &from);
> bool run(void);
> };
>
> void Test::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const
> Address
> &from)
> {
> NS_LOG_INFO("receive packet");
> [...]
> }
>
> bool
> Test::run(void)
> {
> [...] creates nodes [...]
> NS_LOG_INFO ("create socket receive");
> Ptr<SocketFactory> socketFactory= rxNode->GetObject<Udp> ();
> Ptr<Socket> rxSocket= socketFactory->CreateSocket();
> rxSocket=->Bind (InetSocketAddress (Ipv4Address ("10.1.4.2"), 1234));
> rxSocket=->SetRecvCallback (MakeCallback (&Test::ReceivePacket,
> this));
>
> NS_LOG_INFO("send socket ");
> Ptr<SocketFactory> n0SocketFactory = n0->GetObject<Udp> ();
> Ptr<Socket> n0socket = n0SocketFactory->CreateSocket ();
> Ptr<Packet> packet=Create <Packet>();
> NS_LOG_INFO("....");
> n0socket->SendTo (InetSocketAddress (Ipv4Address("10.1.4.2"),
> 1234),packet);
>
> return true;
> }
>
> int
> main (int argc, char *argv[])
> {
> Test teste;
> teste.run();
> [...]
> NS_LOG_INFO ("Run Simulation.");
> Simulator::StopAt (Seconds (3.0));
> Simulator::Run ();
> Simulator::Destroy ();
> NS_LOG_INFO ("Done.");
> }
>
> ----------
>
>
>
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
More information about the Ns-developers
mailing list