|
Q: In class you showed us the output generated when you ran the
test code with your layers.c, can you provide us with this output?
A:I've made an executable available on the CS machines
(works only on a BSD machine like monica.cs.rpi.edu) that you can
play with. You can set a debugging level on the command line and
control how verbose the program is. The program is at
~hollingd/public.html/netprog/P1code/testprog (on the CS machines).
Usage is like this:
testprog [-d #] astring
The program is based on the test code provided for P1 (uses pipes and
fork), the child process sends "astring" to the parent. The lower a
number you specify after "-d", the more debugging output you will see.
-d 3 means only layer 3 prints debugging information.
-d 2 means layer 3 and 2 print debugging information.
-d 1 means layers 3,2 and 1 print debugging information.
-d 0 means layers 0,1,2 and 3 print debugging information
Here is a sample run:
> ./testprog -d 1 "Hello Dave"
Starting - debug level is 1, sending string <Hello Dave>
CID 0 is for pipes 5 and 4
CID 0 is for pipes 3 and 6
[PARENT]:l3_read called - reading at most 100 chars
[CHILD]: l3_write sending Hello Dave
[PARENT]: l2_read called
[CHILD]: l2_write called sending a H
[PARENT]: l1_read called
[CHILD]: l1_write sending: H
[PARENT]: l1_read returning a: H
[CHILD]: l1_read called
[PARENT]: l1_write sending: H
[CHILD]: l1_read returning a: H
[PARENT]:l3_read got a H (72) from l2_read
[CHILD]: l2_write called sending a e
[PARENT]: l2_read called
[CHILD]: l1_write sending: e
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: e
[PARENT]: l1_write sending: e
[CHILD]: l1_read returning a: e
[PARENT]:l3_read got a e (101) from l2_read
[CHILD]: l2_write called sending a l
[PARENT]: l2_read called
[CHILD]: l1_write sending: l
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: l
[PARENT]: l1_write sending: l
[CHILD]: l1_read returning a: l
[PARENT]:l3_read got a l (108) from l2_read
[CHILD]: l2_write called sending a l
[PARENT]: l2_read called
[CHILD]: l1_write sending: l
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: l
[PARENT]: l1_write sending: l
[CHILD]: l1_read returning a: l
[PARENT]:l3_read got a l (108) from l2_read
[CHILD]: l2_write called sending a o
[PARENT]: l2_read called
[CHILD]: l1_write sending: o
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: o
[PARENT]: l1_write sending: o
[CHILD]: l1_read returning a: o
[PARENT]:l3_read got a o (111) from l2_read
[CHILD]: l2_write called sending a
[PARENT]: l2_read called
[CHILD]: l1_write sending:
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a:
[PARENT]: l1_write sending:
[CHILD]: l1_read returning a:
[PARENT]:l3_read got a (32) from l2_read
[CHILD]: l2_write called sending a D
[PARENT]: l2_read called
[CHILD]: l1_write sending: D
[PARENT]: l1_read called
[PARENT]: l1_read returning a: D
[CHILD]: l1_read called
[PARENT]: l1_write sending: D
[CHILD]: l1_read returning a: D
[PARENT]:l3_read got a D (68) from l2_read
[CHILD]: l2_write called sending a a
[PARENT]: l2_read called
[CHILD]: l1_write sending: a
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: a
[PARENT]: l1_write sending: a
[CHILD]: l1_read returning a: a
[PARENT]:l3_read got a a (97) from l2_read
[CHILD]: l2_write called sending a v
[PARENT]: l2_read called
[CHILD]: l1_write sending: v
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: v
[PARENT]: l1_write sending: v
[CHILD]: l1_read returning a: v
[PARENT]:l3_read got a v (118) from l2_read
[CHILD]: l2_write called sending a e
[PARENT]: l2_read called
[CHILD]: l1_write sending: e
[PARENT]: l1_read called
[CHILD]: l1_read called
[PARENT]: l1_read returning a: e
[PARENT]: l1_write sending: e
[CHILD]: l1_read returning a: e
[PARENT]:l3_read got a e (101) from l2_read
[CHILD]: l2_write called sending a
[PARENT]: l2_read called
[CHILD]: l1_write sending:
[CHILD]: l1_read called
[PARENT]: l1_read called
[PARENT]: l1_read returning a:
[PARENT]: l1_write sending:
[CHILD]: l1_read returning a:
[PARENT]:l3_read got a (0) from l2_read
[PARENT]:l3_read returning, got the string <Hello Dave>
MESSAGE RECEIVED WAS <Hello Dave>
|
Problems or questions to hollingd@cs.rpi.edu
|
|
Q: How can layer2 send acknowledgments, from l2_read() I would
somehow need to "know" how to send something to the other end?
A: My description of the "communication endpoints" represented
by the CIDs is incomplete and should include the following statement:
CIDs represent a full duplex communication link.
So, l2_read() can use the CID given to call l1_write() or l1_read().
|
|
Q: What if data is lost? What is bits are reversed? What if the
data is received, but the ACK get's lost. What if a dog eats 3 of
every 8 bits? What if ... ?
A: In general you can't deal with every contingency unless your
code is part of the operating system (and can operate asynchronously).
Don't complicate the assignment, just make sure that your code works as
long as everything else works! This is supposed to be a simple project
that does not involve any system programming (no timers, signals,
interrupts, multiplexed I/O, etc.) that simply makes sure you have
some understanding of layered systems.
|
|
Q: When I implement l2_write(),I add sequencer to the data and
write it. Before sending next data, I call l1_read() to read charactor
ack. If the ack is not I need, then I 'll resend the data. I think I
can't read many times before resending because I have only sent one
byte, so receiver can only send one ack, so I can only read one byte
before sending another data, If I read many times before sending
another byte, the process will block when I read second time because
there is nothing to be read. Am I right? and if the ack is lost or the
byte I have send is lost, then there will be nothing to read, so when
I call L1_read to read ack, the process will block. How to deal this
case? could you give me any hint?
A: Your layer2 protocol is more than requested - you can simplify things
by not resending, just return an error if you get an ACK that is not
what you expect. If you really do resend - I don't know how (using
the scheme you describe), the reader would know what is resent data
and what is not. The purpose of the project is not to create a
bullet-proof reliable service at layer 2, but just to make sure you
understand what a layered system is.
|
Q: in l1_read(int cid, char * buff) Is
buff just a char or is it a string of bits when this function
returns?
A: It is a single char (byte), not a string of bits. You have
to build this value from the 8 bits you (I'm assuming here) read using
l0_read(). In C you can do this with bitwise operators |, &,
<<, and >> . For example, to set the nth bit (rightmost bit is
bit 0) in a char named x to be the value 1 you can do this:
x |= 0x01 << n;
This takes the pattern 00000001, shifts it left n times, and ORs the
result with x (and saves the result of the OR in x). Similarly you can
extract the value of the nth bit with something like this:
bitval = x & (0x01 << n);
Caution: you need to be a little careful about how you do things, the
shift operators depend on whether a value is signed or not. See any
C reference for details.
|
|
Q: What's up with the CS accounts?
A: We requested accounts for all students who were on the
official roster as of Friday, Jan 14th. You should receive email
from labstaff@cs.rpi.edu providing you with the details of your
account on the Computer Science Unix machines. As far as I know this
has not yet happened.
|
|
Q: How do I submit my project?
A: The automated submission script has not yet been
installed, we will provide details when it's ready for action. If it
is not ready by Thursday, Jan 20th we will go with a manual submission
system (email to a human).
|
|
Q: Is there test code available?
A: Yup - it's here
|
|