@@ -539,18 +539,28 @@ client.

Exercise 2. Add code to the section marked "EXERCISE 2". Connect to the server that was given by the command line -arguments char * host and int port. Make sure the +arguments char * host and short port. Make sure the client continues to compile.

-

+

Exercise 3. Add code to the section under the comments marked "EXERCISE 3". First, your code should use send() to send the user-inputted message (char * buf) to the connection you opened. Then, it should call recv() to receive the server's response. Last, it should call write() to print the -response to the screen. -

+response to the screen. + +

+ +N.B.: recv() does not guarantee to return, in a single call, +all of the data that the sender sent. This is because the underlying +implementation of TCP might not have all of the data, or the data might +have been broken into multiple packets, etc. Therefore, when using +recv() on a stream-oriented socket (as is the case here), one +must call recv() in a loop, breaking only when it returns a +non-positive value. +

You can test your client against an echo server that we are running by typing the following. Every time you type something into your client and hit RETURN, your client should print out exactly what you sent. We will keep the echo server running for the duration of the lab, so feel free to test against it at any time.

@@ -657,20 +667,24 @@ argument should be the file descriptor returned by accept(). Make sure that the server continues to compile.

-

+

Exercise 6. Add code to the section under "EXERCISE 6". It's time to implement the echoing behavior. Echoing involves two steps: reading and writing. First, recv() -from your newly created socket, then send() back what you've read. If you want, your server can print out the messages it receives to stdout. As always, be sure to do error checking! -

- +from your newly created socket, then send() back what you've read. If you want, your server can print out the messages it receives to stdout. As always, be sure to do error checking!

+Hint: As with your code for the client, you should call recv() until +it returns a non-positive value (this loop is different from the main +loop mentioned above). +
+

By this point, you have written a compatible network client and network server. Test your programs by running your echo server on linserv1 or linserv2, and connecting to it with a client running somewhere else, as in the example invocation at the beginning of this section. +

Now hand in your work, by following the instructions below.

@@ -1015,7 +1029,7 @@ header (and the file that it is delivering).

You'll work through refitting the echo-server in the following sections:

  1. The server should attempt to parse each new request it receives. -
    +
    Overall, requests are terminated by a double return, corresponding to the characters \r\n\r\n. The difference between \r and \n goes back to the typewriter era. When pressing enter on a physical machine: @@ -1046,7 +1060,7 @@ Key2: Value2
    -Exercise 7. Fill out parse_request(...). For now, we're only interested in the first line. We are expecting to receive specifically a GET method request to a valid page. Your task is to fill out the function. Make sure to read the comments.

    +Exercise 7. Fill out parse_request(...). For now, we're only interested in the first line. We are expecting to receive specifically a GET method request to a valid page. Your task is to fill out the function. Make sure to read the comments. For now, you may assume that you have been passed all the data you will receive via the request argument. (You will ensure this later in Exercise 10.)

    Your code should do exactly the following:

    • Check it fits the form [METHOD] [REQUEST-URI] HTTP/[VERSION] – otherwise return error code @@ -1176,6 +1190,16 @@ the parse_request(...) function as it expects its uri argument to be a buffer large enough to store the entire uri ... you may need to dynamically allocate memory.

      +In keeping with the contract that was codified in Exercise 7, you should be sure your +code passes the full request/headers to the parse_request function. +From before, recall that after calling recv(), +we cannot be sure we have actually received the full message (request+headers) from +the client. As noted above, you can be sure that the client's +request will end in a double return "\r\n\r\n". Modify your original code +to call recv() in a loop until you can be sure you have the full request: +that it has ended appropriately. Only then +should you call your parse_request function.

      + At this point, your server should be nearly functional. One thing remains: serving files.