[ This content is protected and may not be shared, uploaded, or distributed. ]

(Please also check out lecture slides on Sockets Programming, notes on read() and write() system calls, and PA2 FAQ.)

Lab 3 has five parts:

Please note that this lab assumes that you have watched the lecture videos on socket programming.

Part A (lab3a) - echo server and echo client (useful for PA2):

This part has no coding. Do the following in a Terminal:
  • Create an empty directory (call it "lab3") and change directory into it.
  • Download lab3data.tar.gz into that directory and type:
        tar xvf lab3data.tar.gz
    This should create a subdirectory called "lab3data" with the follow files in it:

  • Copy the above files into the current directory by doing (the last character is a period, which refers to the "current working directory"):
        cp lab3data/* .
  • Run another Terminal and cd into the same directory.
  • In the first Terminal window, type "script lab3a-server.script" to start a transcript. Then type the following:
        uname -a
        cat /etc/os-release
        make echo-server
        make echo-client
        ./echo-server 12345
  • In the 2nd Terminal window, type "script lab3a-client.script" to start a transcript
    • Type "./echo-client 12345". Type "Hello World!" and press the <ENTER> key. The client should self-terminate and you should see that the server in the first window says that it has received 13 bytes of data.
    • Type "./echo-client 12345" again. Type "Good-bye for now." and press the <ENTER> key. The client should self-terminate and you should see that the server in the first window says that it has received 18 bytes of data.
    • Type "./echo-client 12345" again. This time, just press the <ENTER> key. The client should self-terminate and you should see that the server in the first window says that it has received 0 bytes of data.
    • Type "exit" to close the client transcript.
  • Go back to the first Terminal and press <Ctrl+c> to kill the echo server. (It's perfectly okay if you see some weird error messages.) Type "exit" to close the server transcript.
Make sure you read the code and understand what's going on and how the echo client communicates/talks to the echo server.

Alternatively, you can also do everything inside one Terminal and run tmux. You can split the screen vertically and run the client and server in separate panes.

Part B (lab3b) - gdb (useful for PA2):

This part has no coding. Run the echo server under gdb to see exactly what the server receives from the echo client:
  • Use the same two Terminals in Part A above.
  • In the first Terminal window, type "script lab3b-server.script" to start a transcript. Then type the following ("(gdb)" is the gdb prompt):
        gdb echo-server
        (gdb) list 76
        (gdb) break 76
        (gdb) break main
        (gdb) run 12345
    When your program gets to the first breakpoint (which is at the beginning of main()), do the following and note the values that's getting printed:
        (gdb) list
        (gdb) print argc
        (gdb) print argv[0]
        (gdb) print argv[1]
        (gdb) cont
    You should see that argc has a value of 2, argv[0] is a C-string that contains the file system path of your program, and argv[1] is the C-string "12345".
  • In the 2nd Terminal window, type "script lab3b-client.script" to start a transcript, then type "./echo-client 12345". Type "Hello!" and press the <ENTER> key.
  • You should break in gdb in the first window. Type the following in gdb and note the values that's getting printed:
        (gdb) l
        (gdb) p bytes_received
        (gdb) p buf[0]
        (gdb) p buf[1]
        (gdb) p buf[2]
        (gdb) p buf[3]
        (gdb) p buf[4]
        (gdb) p buf[5]
        (gdb) p buf[6]
        (gdb) p buf[7]
        (gdb) p buf[8]
        (gdb) p buf[9]
        (gdb) c
    Here's something that's VERY IMPORTANT to understand... You should see that bytes_received is 7, which means that only the first 7 bytes of data in buf[] are valid (i.e., over-written by data read from the socket) and the rest should be treated as garbage (and you should see "garbage" in buf[7], buf[8], and buf[9]). Please note that buf[] is not null-terminated because the echo client did not send a null-terminated C-string and the last character sent by the echo client is the '\n' character (please read the code of "echo-client.cpp" so you understand exactly what's going on).

  • In the 2nd Terminal window, type the following:
        gdb echo-client
        (gdb) list 61
        (gdb) break 61
        (gdb) run 12345
    When prompted by the echo client, type "Bye." and press the <ENTER> key. You should break in gdb on line 61. Type the following in gdb and note the values that's getting printed:
        (gdb) list
        (gdb) p message.c_str()
        (gdb) p message.length()
        (gdb) p message.c_str()[0]
        (gdb) p message.c_str()[1]
        (gdb) p message.c_str()[2]
        (gdb) p message.c_str()[3]
        (gdb) p message.c_str()[4]
        (gdb) c
    You should see that the length of message is 4 and message.c_str() is a C-string (i.e., null-terminated).

  • After you typed "c" in the 2nd window, you should break in gdb in the first window. Type the following in gdb in the first window:
        (gdb) p bytes_received
        (gdb) p buf[0]
        (gdb) p buf[1]
        (gdb) p buf[2]
        (gdb) p buf[3]
        (gdb) p buf[4]
        (gdb) p buf[5]
        (gdb) p buf[6]
        (gdb) p buf[7]
        (gdb) c
    You should see that bytes_received is 5, which means that only the first 5 bytes of data in buf[] are valid and the rest are "garbage". Again, very important, please notice that buf[] is not null-terminated because the echo client did not send a null-terminated C-string.

  • In the 2nd window, type "quit" to get out of gdb and then type "exit" to close the client transcript.
  • Go back to the first Terminal and press <Ctrl+c> to get back into gdb. Type "quit" in gdb to quit gdb. If you are prompted to see if you really want to quit gdb, just type "y". Once you are out of gdb, type "exit" to close the server transcript.

Alternatively, you can also do everything inside one Terminal and run tmux. You can split the screen vertically and run the client and server in separate panes.

Part C (lab3c) - combine the echo server and the echo client into one executable (useful for PA2):

In this part of the lab, you will combine "echo-server.cpp" and "echo-client.cpp" into one file named "lab3c.cpp". When you compile "lab3c.cpp", your executable must be named "lab3c" and this program can run as either the echo server or the echo client, depending on the commandline arguments you give.

The usage information (i.e., commandline syntax) for lab3c is as follows:

    lab3c [-c] PORT
where PORT is a TCP port number. A square-bracketed term in the commandline syntax means that it is an optional commandline argument (with the brackets removed). For this lab, if the "-c" commandline option is included, you must run lab3c identically as the echo client above. If the "-c" is not included, you must run lab3c identically as the echo server above.

VERY IMPORTANT: From this point on, for all your labs and programming assignments, your client and server will always run from the same executable. If a "-c" commandline option is specified in the commandline, you are running as the client. If the "-c" commandline option is not specified in the commandline, you are running as the server.

Please follow the steps below if you are not sure how to do this:

  • Make a copy of "echo-server.cpp" and call it "lab3c.cpp" and leave it in the same "lab3" directory you have created previously.
  • Modify Makefile by adding a new target called lab3c so that when you type "make lab3c", an executable called lab3c will get created. Change the target for "make clean" so that when you type "make clean", lab3c will also get deleted. Type "make lab3c" in the commandline and you should see that an executable called "lab3c" is created. Although this executable is identical to the original echo server.
  • Edit "lab3c.cpp" to include the necessary code from "echo-client.cpp" and change the process_options() function to handle the cases where argc is 2 (run as server) or 3 (run as client). Finally, change main() so that lab3c can run as either the echo server or the echo client.
When you are done, please do the following:
  • Use the same two Terminals in Part A above.
  • In the first Terminal window, type "script lab3c-server.script" to start a transcript. Then type "./lab3c 1000" and you should see an error message saying that you do not have permission to use port number 1000. As it turns out, you cannot bind to any port < 1024.
  • In the first window, type "./lab3c 12345" to run lab3c as an echo server.
  • In the 2nd Terminal window, type "script lab3c-client.script" to start a transcript.
    • Type "./lab3c -c 12345". Type "Hello World!" and press the <ENTER> key and you should see "Hello World!" got echoed back. You should see that in the first window, the server said that it got 13 bytes from the client.
    • Type "./lab3c -c 12345" again, then type "Good-bye for now." and press the <ENTER> key and you should see "Good-bye for now." got echoed back. You should see that in the first window, the server said that it got 18 bytes from the client.
    • Type "./lab3c -c 12345" again, then simply press the <ENTER> key to see that nothing got echoed back. You should see that in the first window, the server said that it got 0 byte of data from the client.
    • Type "exit" to close the client transcript.
  • Go back to the first Terminal and press <Ctrl+c> to kill the echo server. Type "exit" to close the server transcript.
Please note that from this point onward, we will use the same executable for running as a server or a client. Whehter it will run as a server or as a client would depend on whether "argv[1]" is "-c" or not.

Alternatively, you can also do everything inside one Terminal and run tmux. You can split the screen vertically and run the client and server in separate panes.

Part D (lab3d) - modify server and client to handle multiple lines of input (useful for PA2):

In this part of the lab, we will continue with the code you have in Part C above and make the client and the server send and receive multiple lines of text. Please start by making a copy of "lab3c.cpp" and call it "lab3d.cpp". Modify Makefile by adding a new target called lab3d so that when you type "make lab3d", an executable called lab3d will get created. Change the target for "make clean" so that when you type "make clean", lab3d will also get deleted. Type "make lab3d" in the commandline and you should see that an executable called "lab3d" is created. Although this executable is identical to your lab3c. Now you are ready to make changes to "lab3d.cpp".

If we consider a line of text a message, in Part C, our client sends a message to the server and the server echos the message back. When we send multiple messages over the same connection (i.e., without disconnecting and reconnecting), this connection is referred to as a persistent connection. Please note that it's a requirement to be able to handle persistent connections in PA2.

The usage information (i.e., commandline syntax) for lab3d is as follows:

    lab3d [-c] PORT
where PORT is a TCP port number. If the "-c" commandline option is included, you must run lab3d a client. If the "-c" is not included, you must run lab3d as a server.

Modify the server part:

The original server do all the talking with the client inside its talk_to_client() function. It only reads from the socket exactly once and up to 1024 bytes of data using the read() system call. Then it writes everything it reads back into the socket (i.e., "echoes the data") using the write() system call. It then shuts down and closes the socket and close the connection using the shutdown() and close() system call, respectively. Once a socket is shutdown and closed, we will refer to the corresponding connection as an inactive connection (and before that, the connection is active).

For this part of the lab exercise, please modify talk_to_client() to read one line of data at a time and echoes the line back to the client. A line ends when you encounter the first newline character (i.e., '\n', this is also known as the <LF> character)) in the data stream. Please note that the newline character is part of the line. When you echo the line back to the client, you must include the newline character you've read from the data stream. If the line is not an empty line (i.e., contains only the newline character), your server should read more lines and echoes more lines back to the client.

Since you don't know how long a line is and you don't want to read past the end of the current line, you must read a line carefully and you must not call the read() system call in the same way as in the original echo server. Instead of calling read(), you should call the read_a_line() function in "my_readwrite.cpp" (this function was used in part D of Lab 1). Please remember that the read_a_line() ONLY works if the expected data is ASCII text. For this part of the lab, since we are only sending ASCII text characters, read_a_line() is perfect for it. The read_a_line() function has the following function prototype (notice that the first argument is now a socket file descriptor, which is compatible with a regular file descriptor since they are just integers):

    int read_a_line(int socket_fd, string& line);
The line argument is a reference to a C++ string that will contain the data read from the socket. If you have read any data from the socket, the return value of this function must be the number of bytes in line. If there is an error when reading from the socket, read_a_line() will return (-1). If the end of the byte stream has been reached, read_a_line() will return 0. In both of these cases, line does not contain valid data and you must not use it. Furthermore, if you call read_a_line() again, it will keep returning (-1). Therefore, it's best that you don't call it again and you should immediately shutdown and close the connection with the client.

In the original echo server code, we simply call the write() system call to write data into the socket to send a response to the echo client. As it turns out, write() can return when only part of the data has been sent into the socket and you need to call write() again to send the remaining data! This can be a bit messy. So, instead of calling write() directly, you should call the better_write() function in "my_readwrite.cpp". From this point forward, you should always use better_write() to write data into a socket file descriptor and know that better_write() will not return until all the data in the function argument have writting into the socket.

Please note that in "my_readwrite.cpp", there is another function called better_write_header() that would call better_write() if a special debugging flag is turned off (and that flag is off by default). better_write_header() is for the next lab.

In summary, you should change the follow 3 lines in the original echo server from:

    char buf[1024];
    int bytes_received = read(newsockfd, buf, sizeof(buf));
    write(newsockfd, buf, bytes_received);
to:
    string line;
    int bytes_received = read_a_line(newsockfd, line);
    better_write(newsockfd, line.c_str(), bytes_received);

Some students will try to find ways of using C++ code to read data from a socket. Standard C++ does not support networking! Therefore, even if you find some weird way of doing it, it will be non-standard and you will not be permitted to use such code (in all our labs and programming assignments)!

VERY IMPORTANT: In this lab, the client and server only exchange ASCII text characters across a network connection. In general, when you need to read binary data, you must call the read() system call and you must check the return value. If read() returns a negative value, it means that something is wrong with the socket and you should give up on this connection! If it returns zero, it means that end-of-input has been reached and there are no more data coming. When you call read() again, since there is no more data to read, the read() system call would return zero again. If you keep doing this, you will loop indefinitely! Therefore, if read() returns 0, you should do the same thing as if read() has returned a negative value and give up on this connection. It's important to understand that anything can happen to a connection since data is sent across the Internet. Your operating system knows everything about your machine, but can only guess what has happened in the Internet. It tries to summarize what has happened (or what it thinks has happened) to the connection/socket in how the read() system call returns. If you don't handle the read() system call perfectly, you may miss some "signals" from the operating system.

Modify the client part:

For this lab exercise, please also modify the client part to send multiple lines of text (i.e., "messages") to the server over the same connect. The original echo client read one line from the user, writes it into the socket, reads back all the data sent from the server, print it on the screen, then shutdown and close the socket. If the user simply presses <ENTER>, the original echo client does not even send a '\n' to the server. For this part of the lab, if the user simply pressed <ENTER>, you must send an empty line (a line that contains only the '\n' character) to the server.

You should change the code of the client to stay in an infinite loop, read a line of input from the user, send it to the echo server (terminated with '\n'), read a line back from the echo server (using the same read_a_line() code from the modified server), prints it out, and go back to read another line of input from the user again, and so on. We need a way to get out of the infinite loop. For this part of the lab, if you receive an empty line from the server (i.e., a line that has only the '\n' character), your client must break out of the infinite loop then shutdown and close the socket. (Of course, the only way the server will send you an empty line is because the user has typed an empty line, your client sends the empty line to the server, and then server echoes it back to you.)

Finally, it's important that you must not open a new connection to the server to send a new line of message. You must use the same connection (i.e., same socket) to send multiple messages over the same persistent connection.

Running the modified server and client

When you are done, please do the following:
  • Use the same two Terminals in Part A.
  • In the first Terminal window, type "script lab3d-server.script" to start a transcript. Then type "./lab3d 12345".
  • In the 2nd Terminal window, type "script lab3d-client.script" to start a transcript, Then type "./lab3d -c 12345". Type "hello" and press the <ENTER> key. Type "how are you?" and press the <ENTER> key. Type "bye" and press the <ENTER> key. Simply press the <ENTER> key and the client should self-terminate. Type "./lab3d -c 12345" again. Type "testing" and press the <ENTER> key. Type "1" and press the <ENTER> key. Type "2" and press the <ENTER> key. Type "3" and press the <ENTER> key. Simply press the <ENTER> key and the client should self-terminate.
  • Now we are going to intentionally crash your server by sending a non-ASCII character to the server. In the 2nd Terminal window, type "./lab3d -c 12345". Type <Ctrl+l> (i.e., hold down the <Ctrl> key and press the 'l' key) and press the <ENTER> key. The server in the first Terminal window should crash with the following error message (which came from read_a_line() in "my_readwrite.cpp"):
        Encountered a non-ASCII character (0x0c) in read_a_line().  Abort program!
    Your client should self-terminate since its read_a_line() should return (-1) when the server crashed.
  • In the 2nd Terminal window, type "exit" to close the transcript.
  • Type "exit" in the first Terminal to close the transcript.

Alternatively, you can also do everything inside one Terminal and run tmux. You can split the screen vertically and run the client and server in separate panes.

Part E (lab3e) - wireshark (useful for PA2):

This part has no coding. You will learn to use wireshark to "inspect packets" so you can see exactly what "goes on the wire" on the connection between the client and the server. One important thing you need to learn from this class is exactly what "goes over the wire" between any two communicating entities. In this lab exercise, you need to learn how to inspect the "application level" data (i.e., TCP "payload") being exchanged between the client application and the server application.

Please note that wireshark is considered a security risk because it captures all network traffic that your machine can see. Therefore, if you are running on a shared server (such as viterbi-scf1.usc.edu or viterbi-scf2.usc.edu) most likely, wireshark is either unavailable or available only to superusers. If that's the case, please skip this part of the lab (and you will not be able to use wireshark as a tool to debug your future programming assignments).

Once you have learned how to use wireshark to inspect packets, you can use the same technique to inspect packets exchanged between any pair of sender and receive in all the networking programming assignments and future labs. This way, you would know exactly what's being sent from a sender so you can determine if a bug is a sender bug or a receiver bug.

Here's what you should try:

  • Open two Terminal windows and type "sudo wireshark" in the first window. Please enter your admin password when prompted.
  • If you see an "Lua" error saying that something is disabled due to running wireshark as a superuser, just click the OK button and proceed.
  • In the Welcome screen, you must select an interface. For this lab, please double-click on "any". (Later on, when you are doing your programming assignments, you must select the "Loopback: lo" interface instead.)
  • In the text field right below the toolbar, type "tcp.port == 80 && ip.addr == 68.181.32.43" and press <ENTER>.
  • Select "Restart" from the "Capture" menu wireshark to clear the display.
  • In the 2nd Terminal windows, type the following:
        wget -O x http://merlot.usc.edu/
  • In the top pane, click on a line that has "HTTP" in the "Protocol" column.
  • In the middle pane, click on the last line (should say "Hypertext Transfer Protocol").
  • In the middle pane, click on different lines and see how the bottom pane changes. (Can also use the up/down cursor keys on your keyboard to move between lines.)
If you have trouble finding the TCP payload, please ask for help from the CPs!

Repeat what you did when you ran lab3c client against your lab3c server but use "tcp.port == 12345 && ip.addr == 127.0.0.1" instead to look at the messages being exchanged. You should click line by line in the first pane and observe changes in the 2nd pane and look for TCP "Data" lines in the 2nd pane and inspect those packets.

Keep "tcp.port == 12345 && ip.addr == 127.0.0.1" and repeat what you did when you ran lab3d client against your lab3d server. Similarly, you should click line by line in the first pane and observe changes in the 2nd pane and look for TCP "Data" lines in the 2nd pane and inspect those packets.

What you should see is how encapsulation and layering works. TCP "data" is encapsulated inside a TCP "segment", which is encapsulated inside a IP "datagram", which is encapsulated inside a link layer "frame".

Tshark

If you are running on AWS Free Tier, wireshark there is either very very slow or it crashes over VNC. In this case, you can use tshark, which is basically wireshark without the graphical user interface or an interactive user interface. Using tshark, you can capture all the packets just like wireshark and have them go into a file. When you are done capturing all the data, run tshark to print everything you would see in wireshark so you can inspect all the packets that were captured. To install tshark, please do:
    sudo apt-get install tshark
    sudo chmod +x /usr/bin/dumpcap
Let's try the following:
  • Open three Terminal windows and type the follwoing into the first window to capture TCP data created when you run lab3c:
        tshark -i lo -w test.pcap -f "host 127.0.0.1" -f "tcp port 12345"
    In the above command, "lo" refers to the "loop-back" interface (i.e., IP address 127.0.0.1) and the argument following the "-w" commandline option is the name of the output file. Please use the file name extension ".pcap" to mean that the file is a "raw data capture (binary) file".
  • In the 2nd Terminal windows, type the following to run your lab3c echo server:
        ./lab3c 12345
  • In the 3rd Terminal window, type the following go run your lab3c echo client:
        ./lab3c -c 12345
    At the lab3c echo client prompt, type "Hello World!" and press <ENTER>.
  • In the first window, press <Ctrl+C> to kill the tshark program.
  • In the 2nd window, press <Ctrl+C> to kill the lab3c echo server.
  • In the first window, type the following to see a top-level summary of the packets you have captured:
        tshark -r test.pcap --color
    The first number in each line is referred to as a "frame number". Please note that the color you see is usually the same color you would have seen in wireshark!
  • In the 2nd window, type the following to create a full dump of the packets you have captured and we will send the printout into a text file:
        tshark -r test.pcap -V -x > test.out
  • You can open test.out with a text editor to examine what's in every captured packet.
  • In the first window, look for TCP frames that contain [PSH, ACK] in the summary printout and find the corresponding frame in test.out and see if you can find "Hello World!\n" near the end of that frame. Each such frame is often referred to as a "TCP segment" and the payload of such a segment is "application data" (i.e., what you wrote into a TCP socket).

    For example, you may see something like the following in the hexdump portion of a frame (the colors are mine):

        0000  00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00   ..............E.
        0010  00 41 e4 78 40 00 40 06 58 3c 7f 00 00 01 7f 00   .A.x@.@.X<......
        0020  00 01 95 e4 30 39 7d 84 e3 7e 38 3e 40 7d 80 18   ....09}..~8>@}..
        0030  01 56 fe 35 00 00 01 01 08 0a 00 b8 61 ae 00 b8   .V.5........a...
        0040  5d 47 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0a      ]GHello World!.
    Each row is 16 bytes of data. Start from the beginning and look for the pattern "08 00" (which means that the next layer is an IPv4 packet). Everything up to that point belong to the packet capture mechanism and we should ignore that. In the above example, looks like the first 14 bytes belongs to the packet capture mechanism. The next part (in blue) is the IP header (typically 20 bytes long). The next part is the TCP header, which must be at least 20 bytes long. The first 4 bits of byte 12 (the first byte being byte 0) in this part is known as TCP's "header length" and it says how many 32-bit words is the TCP header. In the above example, "header length" is 8 (in red). Therefore, TCP header (in green) is 32 bytes long. The remaining data is TCP payload, which is application data. As you can see, the application data (in orange) is 13 bytes long and it's the string "Hello World!\n".

    Please look over more descriptive information in test.out about this particular frame. They may not make much sense and that's okay. This is the same information that's presented in wireshark.

The above specificiation has quite a lot of details! So, pseudo-code for the code you need to write is not provided.

Below is the grading breakdown:
  • (1 pt) submitted a valid lab3.tar.gz file with all the required files using the submission procedure below
  • (0.5 pt) contents in "lab3a-server.script" and "lab3a-client.script" are correct
  • (0.5 pt) contents in "lab3b-server.script" and "lab3b-client.script" are correct
  • (0.5 pt) contents in "lab3c-server.script" and "lab3c-client.script" are correct
  • (0.5 pt) contents in "lab3d-server.script" and "lab3d-client.script" are correct
  • (1 pt) "Makefile" works for "make lab3c" and "make lab3d"
  • (0.5 pt) source code of your modified echo server program looks right
  • (0.5 pt) source code of your modified echo client program looks right
Minimum deduction is 0.5 pt for anything that's incorrect. Please note that for the "Makefile" item, you can only get credit for it if your "source code" is relevant to this lab; therefore, you can only get as many points as the "source code" item in the best case.

Please keep in mind that even though lab grading is "light", it doesn't mean that you can just put anything into your submission! It's still your responsibility to make sure that the files in your submission contains information that's relevant to the tests you were supposed to run. Use the "more" command to view your script/log files to make sure that they contain the right information. If a file has the wrong stuff in it, you should delete it and create the file again and verify. If most of the stuff in your script/log files are wrong and you did not notice it, we will most likely have to take points off.

To submit your work, you must first tar all the files you want to submit into a tarball and gzip it to create a gzipped tarfile named "lab3.tar.gz". Then you upload "lab3.tar.gz" to our Bistro submission server.

Change into the "lab3" directory you have created above and enter the following command to create your submission file "lab3.tar.gz" (if you don't have any ".h" files, don't include "*.h*" at the end):

    tar cvzf lab3.tar.gz lab3*.script Makefile *.c* *.h*
    ls -l lab3.tar.gz
The last command shows you how big the created "lab3.tar.gz" file is. If "lab3.tar.gz" is larger than 1MB in size, the submission server will not accept it.

If you use an IDE, the IDE may put your source code in subdirectories. In that case, you need to modify the commands above so that you include ALL the necessary source files and subdirectories (and don't include any binary files) ane make sure that your code can be compiled without the IDE since the grader is not allowed to use an IDE to compile your code.

You should read the output of the above commands carefully to make sure that "lab3.tar.gz" is created properly. If you don't understand the output of the above commands, you need to learn how to read it! It's your responsibility to ensure that "lab3.tar.gz" is created properly.

To check the content of "lab3.tar.gz", you can use the following command:

    tar tvf lab3.tar.gz
Please read the output of the above command carefully to see what files were included in "lab3.tar.gz" and what are their file sizes and make sure that they make sense.

Please enter your USC e-mail address and your submission PIN below. Then click on the Browse button and locate and select your submission file (i.e., "lab3.tar.gz"). Then click on the Upload button to submit your "lab3.tar.gz". (Be careful what you click! Do NOT submit the wrong file!) If you see an error message, please read the dialogbox carefully and fix what needs to be fixed and repeat the procedure. If you don't know your submission PIN, please visit this web site to have your PIN e-mailed to your USC e-mail address.

When this web page was last loaded, the time at the submission server at merlot.usc.edu was 27Nov2025-18:59:19. Reload this web page to see the current time on merlot.usc.edu.

USC E-mail:    @usc.edu
Submission PIN:  
Event ID (read-only):  
Submission File Full Path:  
   
 
If the command is executed successfully and if everything checks out, a ticket will be issued to you to let you know "what" and "when" your submission made it to the Bistro server. The next web page you see would display such a ticket and the ticket should look like the sample shown in the submission web page (of course, the actual text would be different, but the format should be similar). Make sure you follow the Verify Your Ticket instructions to verify the SHA1 hash of your submission to make sure what you did not accidentally submit the wrong file. Also, an e-mail (showing the ticket) will be sent to your USC e-mail address. Please read the ticket carefully to know exactly "what" and "when" your submission made it to the Bistro server. If there are problems, please contact the instructor.

It is extreme important that you also verify your submission after you have submitted "lab3.tar.gz" electronically to make sure that every you have submitted is everything you wanted us to grade. If you don't verify your submission and you ended up submit the wrong files, please understand that due to our fairness policy, there's absolutely nothing we can do.

Finally, please be familiar with the Electronic Submission Guidelines and information on the bsubmit web page.