Practical 1: Non-blocking Web serverDue Friday by 17:00 Points 35 Available until Jun 21 at 23:59Please Note: Before attempting this practical please study the material on Sockets. pdfand the tutorials under Week 2 lecture materials I will not be covering socketprogramming in the lecture and this is left for you as a learning exercise and part ofpractical 3. If you are having a lot of issues with coding, please see the helpful staff at theComputer Science Learning Center Learning Outcomes1. Reading a Protocol SpecificationMost of the application layer protocols are relatively simple and text-based. This exercise gets youto first read the protocol specification(s). The RFC documents are not very typical of a standardsdocument - they are very compact. They are also somewhat incomplete - they come with astandard reference implementation which is used to resolve ambiguities in the specification. Sothe first learning outcome is the ability to read a protocol specification.2. Practical Experience with Socket APIThe second outcome is some practical experience with using the socket API. This is quitestraightforward in reality, but there are quite a few not immediately obvious tricks.3. Understanding the HTTPThe third learning outcome is a detailed knowledge of the protocol itself. HTTP is simple and notdissimilar to many other application layer protocols. Once you see how this works, it becomesmuch easier to implement other protocols (Simple Mail Transfer Protocol, SMTP, for example) andto add functionality to existing applications (send this information to a friend)Note that the focus is not the programming but the protocol. There are generally librariesavailable in high-level languages that support HTTP and other protocols. If you werebuilding a service you would most likely use these libraries rather than working at thesocket layer. However, those libraries hide much of the protocol behavior we are trying tostudy, which is our motivation for working at the socket layer.Acknowledgement: This assignment is Adapted from Kurose & Ross - Computer Networking: atop-down approach featuring the Internet. It is not the same though so make sure you arefollowing the specifications and using the provided code from this practical sheet and not thetextbook or website.CBOK categories: Abstraction, Design, Data & Information, Networking, and Programming.Submitting your assignmentYou will need to keep your files in SVN. If you arent familiar with SVN, the following SVN noteswill assist you.The handin key for this practical is / //cna/webserverYou can submit and automatically mark your assignment by following this link(https://cs.adelaide.edu.au/services/websubmission/) to the web-submission system. Note that this isjust a preliminary test to make sure your Web server meets the basic functionality. Its yourresponsibility to ensure it meets the specifications for the methods your are asked to implement inthis practical.Template filesThis practical comes with a skeleton web server and helper methods to reduce complexity.Download and extract the following zip file into your repository.prac1_files.zipWe will go through these files in the next section.The practical is set up so that all code you need will belong inside the comment tags below, whereX ranges from 1 to 11.IntroductionIn this practical, we will develop a web server. In the end, you will have built a non-blocking webserver that is capable of processing multiple simultaneous service requests in parallel. You should/* START CODE SNIPPET X */.../* END CODE SNIPPET X */123be able to demonstrate that your Web server is capable of delivering your home page to a webbrowser and that your server returns standards compliant responses.Resources to studyTo understand the data that is sent to and from a web server you will need to study the HTTP. Usethe following resources and sections to help you understand the key data points that need to besent and received.RFC 1945 (https://www.cs.adelaide.edu.au/users/third/cn/RFCs/rfc1945.txt)Wireshark HTTP lab quizVerbose cUrl commandFor the purposes of this practice we will only be looking at HTTP/1.1 and older requests. HTTPSrequests are out of the scope of this practical.RFC 1945Most of the application layer protocols are relatively simple and text-based. The RFC documentsare not very typical of a standards document - they are very compact. They are also somewhatincomplete - they come with a standard reference implementation which is used to resolveambiguities in the specification. It is important to be able to read a protocol specification.For this practical, you will need to understand the lines (text) that gets sent to the server on anHTTP request, and (at the very least) the first line that is returned. Scan the contents page for thekeywords; request and response.Wireshark HTTP Lab QuizIn doing the Wireshark HTTP lab, you would have seen the data that is sent to and from a webserver. There is a lot of extraneous data that is sent which is beyond the scope of this practical.Identify the key data bits of data.Food for thought: What data would you change to cause the HTTP request to fail?Verbose cUrl commandThe cUrl command is a command line web request tool. By enabling the -v (verbose) option youcan see the data sent to and from a web server.The following command is to the URI http://jsonplaceholder.typicode.com/todos/1(http://jsonplaceholder.typicode.com/todos/1)1 $ curl -v http://jsonplaceholder.typicode.com/todos/1In the output above > denotes data sent to the server and server. Study lines 4, 5, 6 and 10 from the above carefully.Compile and RunTo compile the Web server run:To run the Web server run:When you run the program for the first time it will terminate with no output. That is ok for now, we* Trying 104.24.106.213...* TCP_NODELAY set* Connected to jsonplaceholder.typicode.com (104.24.106.213) port 80 (#0)> GET /todos/1 HTTP/1.1> Host: jsonplaceholder.typicode.com> User-Agent: curl/7.54.0> Accept: */*>{ userId: 1, id: 1, title: delectus aut autem, completed: false* Connection #0 to host jsonplaceholder.typicode.com left intact1 $ gcc helpers.c web_server.c -o web_server1 $ ./web_server [port]will fix them in as we go along.In the following steps, we will go through the code for the first implementation of the Web server inC. Follow along with the web_server.c file.Non-blockingOur first implementation of the Web server will be non-blocking, where the processing of eachincoming request will take place inside a separate process. This allows the server to servicemultiple clients in parallel, or to perform multiple file transfers to a single client in parallel.In the code below, this is done with fork() . This creates a new process with a copy of the originalprocess variables. Threads can also be used to serve multiple requests in parallel. In this case,both threads share variables. This is more efficient as a copy doesnt have to be made, but it alsorequires care to make sure that both threads dont try to change values at the same time and thatchanges happen in the right order. If you are keen to use threads instead, you are welcome tochange the code.The basic structure of the code is:The parent code will listen for new connection requests and each time a new connection isreceived a child is created and will run code to handle the new connection: reading the HTTPrequest and sending an HTTP response on the connection.The parent will continue separately and go back to the start of the loop accepting furtherint main(int argc, char *argv[]){ while (true) { if ((pid = fork()) == 0) { /*----------START OF CHILD CODE----------------*/ /* We are now in the child process */ ... /* All done return to parent */ exit(EXIT_SUCCESS); } /*----------END OF CHILD CODE----------------*/ /* Back in parent process * if child exited, wait for resources to be released */ waitpid(-1, NULL, WNOHANG);connections.VariablesThe main program starts by defining variables that will be used in the code.It is important to understand the purpose of each variable.The server will have two sockets:1. The listen_socket variable is for the socket that listens and accepts new requests2. The connection_socket variable is to hold the connection to a client.It is very important that you send and receive requests on the correct socket.The response_buffer is just a variable to hold the response that your server will send back to theclient. It is set to the maximum response size which can be changed in the config.h file.status_code and status_phrase will be used to hold the HTTP response code and phrase thatshould be sent back to the client.Step 1: Create a socketThe first step for the server is to create a socket. You will need to write the code to create thesocket. Be sure to use the correct variable (either listen_socket or connection_socket ).If you are not sure how to create a socket referer to:The lecture notessocket man page $ man 2 socketint main(int argc, char *argv[]){ /* structure to hold servers and client addresses, respectively */ struct sockaddr_in server_address, client_address; int listen_socket = -1; int connection_socket = -1; int port = 0; /* id of child process to handle request */ pid_t pid = 0; char response_buffer[MAX_HTTP_RESPONSE_SIZE] = ; int status_code = -1; char *status_phrase = ;Online socket tutorial (https://www.binarytides.com/socket-programming-c-linux-tutorial/)Specifying the portNormally, Web servers process service requests that they receive through the well-known portnumber 80. You can choose any port higher than 1024, but remember to direct any requests toyour Web server with the corresponding port. The following code sets the port to either the valuetyped on the command line, or if no port is given, then the DEFAULT_PORT , which is defined in theconfig.h file.Steps 2 & 3: Binding/* 1) Create a socket *//* START CODE SNIPPET 1 */.../* END CODE SNIPPET 1 */1234/* Check command-line argument for port and extract * port number if one is specified. Otherwise, use default */if (argc > 1){ /* Convert from string to integer */ port = atoi(argv[1]);}else{ port = DEFAULT_PORT;}if (port { /* Test for legal value */ fprintf(stderr, bad port number %d\n, port); exit(EXIT_FAILURE);}Next, you need to bind the socket you created to the port and network interfaces that it shouldlisten to. You will need to write the code to set the correct values in the server_address structureand call bind() to bind the address information to the socket.The memset function makes sure that serv_addr doesnt have any values in it (i.e. it will clear thedata structure so that it contains all 0s).See $ man 2 bind for how to use the bind() methodSee https://linux.die.net/man/7/ip (https://linux.die.代写Web server作业、代写web/HTML程序语言作业、代做web课程设计作业 代做Python程序|代写Pytnet/man/7/ip) on how to set the values inserv_addr.Steps 4 & 5: ListeningThe server should now start listening for a TCP connection request on the socket. Once it islistening, it can begin accepting connections. Because we will be servicing request messagesindefinitely, we place the accept request operation inside of an infinite loop. This means we willhave to terminate the Web server by pressing ^C (Ctrl-C) on the keyboard./* 2) Set the values for the server address structure *//* START CODE SNIPPET 2 */.../* END CODE SNIPPET 2 *//* 3) Bind the socket to the address information set in server_address *//* START CODE SNIPPET 3 */.../* END CODE SNIPPET 3 */You need to add the code to make the socket listen and to accept a connection.the accept method will block until a connection is made.See $ man 2 listen and $ man 2 accept for how to use the listen() and accept() methodsHandling a connectionWhen a connection request is received, we create a child process to handle the request in aseparate process and close any sockets the child is not using (remember the child gets a copy ofthe sockets. Closing the child socket does not close the parents copy only its own copy).After the child has started execution, the main (parent) process closes its copy of the connectedsocket and returns to the top of the request processing loop to accept another connection. Themain process will then block, waiting for another TCP connection request, while the child continuesrunning. When another TCP connection request is received, the main process goes through thesame process of child process creation regardless of whether the previous child has finishedexecution or is still running.Note the wait() call below allows the system to free up resources from the child when a childexits. If no child has exited, wait() with NOHANG returns immediately./* 4) Start listening for connections *//* START CODE SNIPPET 4 */.../* END CODE SNIPPET 4 *//* Main server loop * Loop while the listen_socket is valid */while (listen_socket >= 0){ /* 5) Accept a connection */ /* START CODE SNIPPET 5 */ ... /* END CODE SNIPPET 5 *//* Fork a child process to handle this request */if ((pid = fork()) == 0)Step 6: Reading the requestOnce we have closed the listen_socket in the child process, we create an http_request structurewhich will be used to store the information about the HTTP request, such as its method and URIand pass this structure to the helper function Parse_HTTP_Request() . This helper will read therequest from the given socket and fill in the http_request structure for you. The interfaceinformation about the helper functions is in the file helpers.h and the file helpers.c contains theimplementation. Note that we have provided these to help you and are not supposed to be anexhaustive list of functions required to complete the practical. However, most of what youneed is given to you in these helper files so the helper files tries to make this practicalmuch easier for you by doing most of the hard work for you.new_request will now be filled with the method and URI that the client sent. /*----------START OF CHILD CODE----------------*/ /* We are now in the child process */ /* Close the listening socket * The child process does not need access to listen_socket */ if (close(listen_socket) { fprintf(stderr, child couldnt close listen socket\n); exit(EXIT_FAILURE); } ... /* All done return to parent */ exit(EXIT_SUCCESS);}/*----------END OF CHILD CODE----------------*/.../* if child exited, wait for resources to be released */waitpid(-1, NULL, WNOHANG);/* See httpreq.h for definition */struct http_request new_request;/* 6) call helper function to read the request * this will fill in the struct new_request for you * see helper.h and httpreq.h *//* START CODE SNIPPET 6 */.../* END CODE SNIPPET 6 */Closing the connectionFinally, the child is finished and can close any sockets it still has open and exit.Now we are ready to connect to a browser.Connecting to a browserAfter your program successfully compiles, run it with an available port number (e.g. 8080, 9000,etc), and try contacting it from a browser.Enter http://localhost:[port]/index.html into the address bar of your browser, replacing [port]with the port number for your Web server and press enter. The browser will display an errorbecause our Web server has accepted the request, closed the connection and not sent anything/* Back in parent process * Close parents reference to connection socket, * then back to top of loop waiting for next request */if (connection_socket >= 0){ if (close(connection_socket) { fprintf(stderr, closing connected socket failed\n); exit(EXIT_FAILURE); }}/* if child exited, wait for resources to be released */waitpid(-1, NULL, WNOHANG);back.In the terminal (that is running your Web server) the server should display the contents of theHTTP request message.Step 7: Parsing HTTP RequestInstead of simply displaying the browsers HTTP request message, we will analyze the requestand send an appropriate response. We are going to ignore the information in the header lines, anduse only the path contained in the request line.You now need to write code that will decide, based on the results from Parse_HTTP_Request() , whatthe status_code and status_phrase variables should be set to for the response.Your server is required to handle and return the correct status code and phrase for Your server is required to handle and return the correct status code and phrase forWaiting connection on port 8080...received request: GET /index.html HTTP/1.1Host: localhost:8080Connection: keep-aliveUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, likeAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflate, brAccept-Language: en-AU,en;q=0.9,en-US;q=0.8Method is: GETURI is: /index.htmlversion is: HTTP/1.1Sending response line:the following situations the following situations:1. The requested resource is found2. The requested resource is not found3. The requested method isnt implemented (your server will only implement GET and HEADmethods)4. The client sent an invalid requestLook in the RFC 1945 (https://www.cs.adelaide.edu.au/users/third/cn/RFCs/rfc1945.txt) specificationto work out the most suitable status code and phrase.You can use the -X [method] option in cUrl to run web requests on your Web server.Fill in the code needed at:Having determined the appropriate response, we can now send the response header. Check theHTTP response format to make sure you fill this in correctly!Step 8: Formatting the responseStep 9: Sending the responseNow we can send the status line and our header lines to the browser by writing to the socket. Besure you send to the correct socket.1 $ curl -v -X GET localhost:8080/index.html/* 7) Decide which status_code and reason phrase to return to client *//* START CODE SNIPPET 7 */.../* END CODE SNIPPET 7 *//* 8) Set the reply message to the client * Copy the following line and fill in the ?? * sprintf(response_buffer, HTTP/1.0 %d %s\r\n, ??, ??); *//* START CODE SNIPPET 8 */sprintf(response_buffer, HTTP/1.0 %d %s\r\n, ??, ??);/* END CODE SNIPPET 8 */printf(Sending response line: %s\n, response_buffer);/* 9) Send the reply message to the client * Copy the following line and fill in the ?? * send(??, response_buffer, strlen(response_buffer), 0); *//* START CODE SNIPPET 9 */Steps 10 & 11: Preparing a HTTP ResponseNow that the status line has been placed on the socket on its way to the browser, it is time to dothe same with the response headers and the entity body. We need to decide whether or not anentity body should be returned.You will need to understand the difference between GET and HEAD.We can use the helper methods Is_Valid_Resource() to see if the requested file exists. If therequested file does exist, we can call helper function Send_Resource() to send the Content-Lengthheader and the file contents on the socket (see helpers.h for how to use Is_Valid_Resource()and Send_Resource() ).After sending the entity body, the work in the child has finished, so we close the socket beforeterminating.Running the Web serverWhen you have completed all the steps correctly your web browser will be able to respond with amessage when running http://localhost:[port]/index.htmlsend(??, response_buffer, strlen(response_buffer), 0);/* END CODE SNIPPET 9 */89bool is_ok_to_send_resource = false;/* 10) Send resource (if requested) under what condition will the * server send an entity body? *//* START CODE SNIPPET 10 */is_ok_to_send_resource = .../* END CODE SNIPPET 10 */if (is_ok_to_send_resource){ Send_Resource(connection_socket, new_request.URI);}else{ /* 11) Do not send resource * End the HTTP headers * Copy the following line and fill in the ?? * send(??, \r\n\r\n, strlen(\r\n\r\n), 0); */ /* START CODE SNIPPET 11 */ send(??, \r\n\r\n, strlen(\r\n\r\n), 0); /* END CODE SNIPPET 11 */Prac 1: Web Proxy (1)Criteria Ratings Pts1.0 pts4.0 ptsYou should also make sure that your Web server will work with HEAD and other requests. Youmay use the cUrl command to test your web server.Last WordsWe have only coded the very basics of a web server. There is a lot of missing, for instance, we donot return the content type of the file, we dont return an entity body when there is an error (whichmeans nothing will be displayed in the browser when an error occurs). If you have extra time, lookat implementing some of these.This completes the code for the second phase of development of your Web server. Try addingsome web pages or text files to the RESOURCE_PATH directory (the RESOURCE_PATH directory isdefined in config.h ) Create this directory where you are running the server and try viewing yourfiles with a browser. Remember to include a port specified in the URL of your home page, so thatyour browser doesnt try to connect to the default port 80.When you connect to the running web server with the browser, examine the GET messagerequests that the web server receives from the browser. You can use a tool called telnet to checkthat your server responds correctly to HEAD requests.Successful compilation of code based on the skeleton provided.If your server crashes for reasons that are not due to a failure of thewebsubmission system (for example submitting solutions that are nottested on the University Linus image or with inadequate amount of testingand with software bugs), we will perform no further manual inspections ortesting and you will receive an automatic ZERO for the whole assignment.1.0 ptsServer started up successfullyIf your server crashes for reasons that are not due to a failure of thewebsubmission system (for example submitting solutions that are nottested on the University Linus image or with inadequate amount of testingand with software bugs), we will perform no further manual inspections or4.0 ptstesting and you will receive an automatic ZERO for the whole assignment.Server acceptance of client request for html file and correct response 5.0 ptsCorrect server behaviour for a request for non existent file 5.0 ptsFullCorrect server behaviour to a HEAD method 5.0 ptsCorrect server behaviour to an unimplemented method 5.0 ptsCorrect sever behaviour for a bad request 5.0 ptsServer successfully handles multiple requests (non-blocking) 5.0 pts转自:http://www.6daixie.com/contents/19/5011.html