1 / 23

A ‘minimal’ web-server

A ‘minimal’ web-server. We can glean insights about the operation of the HTTP protocol if we create our own web-server. A web-browser is our ‘client’. Mozilla Firefox. Our ‘mini’ server. Request-message (to server). HTTP request line. Request ‘headers’. Optional ‘body’.

leola
Download Presentation

A ‘minimal’ web-server

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. A ‘minimal’ web-server We can glean insights about the operation of the HTTP protocol if we create our own web-server

  2. A web-browser is our ‘client’ Mozilla Firefox Our ‘mini’ server Request-message (to server) HTTP request line Request ‘headers’ Optional ‘body’ Response-message (to client) HTTP status line Response ‘headers’ Optional ‘body’

  3. TCP server ‘boilerplate’ • By now we have seen that any connection oriented ‘server’ has some standard steps to execute by way of ‘connection-setup’ • Initialize a host ‘socket-address’ structure • Create a TCP socket to use for ‘listening’ • Bind the ‘socket-address’ to this socket • Enable the socket to ‘reuse’ its port-number • Convert the socket into a ‘listening’ socket • Accept a ‘connection-request’ from a client

  4. ‘helper’ functions • We can employ standard library-functions to help setup the internet socket-address data-structure for our server’s host: • ‘gethostname()’ • ‘gethostbyname()’ • ‘inet_ntoa()’ • ‘inet_addr()’ • ‘htons()’

  5. Our ‘sockaddr_in’ setup struct sockaddr_in sin_family sin_port sin_addr padded with zeros

  6. Setup our ‘listening’ socket

  7. ‘iterative’ server-design ‘accept’ a connection-request from a client ‘receive’ the HTTP request-message We use some new ‘helper’ functions for these steps validate and process the HTTP command ‘send’ the HTTP response-message ‘close’ the connection with this client

  8. ‘fdopen()’ • To conveniently process the incoming stream of characters in a client’s HTTP request-message (which is organized into lines of text with CRLF as the line-delimiter), and to conveniently reply with similarly organized lines of text, we would like to use the standard ‘buffered’ i/o functions • To do this requires substituting ‘streams’ for our TCP ‘connection’ socket, which is accomplished by using the ‘fdopen()’ library-function

  9. ‘fdopen()’ and ‘dup()’ • To conveniently process the incoming stream of characters in a client’s HTTP request-message (which is organized into lines of text with CRLF as the line-delimiter), and to conveniently reply with similarly organized lines of text, we would like to use the standard ‘buffered’ i/o functions • To do this will require us to associate ‘streams’ with our TCP ‘connection’ socket, one for input, one for output, which we can accomplish using the ‘fdopen()’ and ‘dup()’ library-functions

  10. Our i/o streams • Our connection-socket is named ‘conn’: • We associate an input-stream with ‘conn’: • And we associate an output-stream with a ‘duplicate’ of our connection-socket ‘conn’: struct sockaddr_in caddr = { 0 }; socklen_t salen = sizeof( caddr ); int conn = accept( sock, (sockaddr*)&caddr, &calen ); FILE *rx = fdopen( conn, “r” ); FILE *tx = fdopen( dup( conn ), “w” );

  11. Request message’s lines • Now it’s easy to receive the first ‘line’ of an HTTP request-message sent by our client: • The remaining lines (request headers and the empty line) can be received like this: char request[ BUFSIZ ] = { 0 }; fgets( request, BUFSIZ, rx ); char header[ BUFSIZ ] = { 0 }; while ( fgets( request, BUFSIZ, rx ) ) if ( strcmp( header, “\r\n” ) == 0 ) break;

  12. Parsing the ‘request’ • The HTTP Request-line is comprised of three fields, separated by a blank-space and terminated with the CR/LF delimiter • We can use the formatted string-scan function ‘sscanf()’ to parse the request <COMMAND> <RESOURCE> <VERSION> ”\r\n” char cmd[ BUFSIZ ] = { 0 }, arg[ BUFSIZ ] = { 0 }; strcpy( arg, “./” ); // for restricting the client’s access if ( sscanf( “%s%s”, cmd, arg+2 ) != 2 ) { perror( “sscanf” ); }

  13. Validating the request • For now our ‘miniature’ web-server only accepts the basic HTTP ‘GET’ command: if ( strcmp( cmd, “GET” ) != 0 ) { // the HTTP Response status, headers, and empty line fprintf( tx, “HTTP/1.0 501 Not Implemented \r\n” ); fprintf( tx, “Content-type: text/plain \r\n” ); fprintf( tx, “\r\n” ); // the HTTP Response-message’s ‘body’ fprintf( tx, “That one is not yet implemented \r\n” fclose( rx ); fclose( tx ); continue; }

  14. ‘nonexistent’ resource? • The ‘stat()’ library-function can be used to verify that a requested resource exists struct stat info = { 0 }; if ( stat( arg, &info ) < 0 ) // the target does not exist { // the HTTP Response’s status, headers, and empty line fprintf( tx, “HTTP/1.0 404 Not Found \r\n” ); fprintf( tx, “Content-type: text/plain \r\n” ); fprintf( tx, “\r\n” ); // the HTTP Response-message’s ‘body’ fprintf( tx, “Requested item not found \r\n” fclose( rx ); fclose( tx ); continue; }

  15. ‘struct stat’

  16. ‘statdemo()’ • We have posted a demo-program which lets you see the information about a file which the Linux operating system keeps track of (including the ‘type’ of the file) EXAMPLE: $ ./statdemo mywebsvr.cpp

  17. ‘folder’ or ‘file’? • Our server can send its client a directory-listing if that type of resource is requested if ( S_ISDIR( info.st_mode ) ) // the requested resource is a directory { // the HTTP Response’s status, headers, and empty line fprintf( tx, “HTTP/1.0 200 OK \r\n” ); fprintf( tx, “Content-type: text/plain \r\n” ); fprintf( tx, “\r\n” ); // the HTTP Response-message’s ‘body’ fflush( tx ); if ( fork() == 0 ) // child-process will deliver the directory-listing { dup2( conn, 1 ); dup2( conn, 2 ); close( conn ); execlp( “ls”, “ls”, “-l”, arg, NULL ); exit( 1 ); } wait( NULL ); // parent-process will sleep until tge child exits fclose( rx ); fclose( tx ); continue; }

  18. A sample web-page • We created a tiny webpage example for demonstrating our web-server’s ability to deliver an ‘HTML’ file to a web-browser

  19. Delivering an ‘html’ file if ( strcmp( strrchr( arg, ‘.’ ) + 1, “html” ) == 0 ) // the requested resource is an ‘html’ file { // the HTTP Response’s status, headers, and empty line fprintf( tx, “HTTP/1.0 200 OK \r\n” ); fprintf( tx, “Content-type: text/html \r\n” ); fprintf( tx, “\r\n” ); // the HTTP Response-message’s ‘body’ fflush( tx ); if ( fork() == 0 ) // child-process will deliver the file’s contents { dup2( conn, 1 ); dup2( conn, 2 ); close( conn ); execlp( “cat”, “cat”, arg, NULL ); exit( 1 ); } wait( NULL ); // parent-process will sleep until the child exits fclose( rx ); fclose( tx ); continue; }

  20. ‘mywebsvr.cpp’ • We posted this miniature web-server on our course website for you to download • You can use Linux’s ‘Firefox’ browser to see if indeed it can deliver the sample HTML-file (named ‘mywebpage.html’) • First start the web-server application, then launch ‘Firefox’ and type in this URL: <http://hrn235xx:54321/mywebpage.html> Your classroom host’s station-number

  21. In-class exercise #1 • Try using Microsoft’s Internet Explorer to request the ‘mywebpage.html’ document • Edit your copy of ‘mywebpage.html’ to add the following attributes within the <body> tag in that HTML document: <body text=“#00FF00” bgcolor=“#0000FF”>

  22. In-class exercise #2 • Copy the file named ‘warrior.jpg’ from our course website into your local directory • Then modify the ‘mywebpage.html’ file by adding this extra line in front of </body>: <img src=“warrior.jpg”> • Now extend the functionality of our ‘mini’ web-server by adding a block of new code which enables a child-process to deliver an image-file having the ‘.jpg’ file-suffix

  23. Exercise #2 (continued) • You can do this with your Editor by using ‘copy-and-paste’ applied to the code-block that delivers an ‘html’ file to a client – just change the ‘html’ file-suffix to ‘jpg’, and change the ‘Content-type’ statement so that ‘text/html’ becomes ‘image/jpeg”

More Related