PPT

46
1 Networking Programming

Transcript of PPT

Page 1: PPT

1

Networking Programming

Page 2: PPT

2

Outline

• Web servers– HTTP Protocol

– Web Content

– CGI

• The Tiny Web Server

• Suggested Reading:– 12.5~12.6

Page 3: PPT

3

• Clients and servers communicate using the HyperText Transfer Protocol (HTTP)– client and server establish TCP connection

– Client requests content

– Server responds with requested content

– client and server close connection (usually)

• Current version is HTTP/1.1

– RFC 2616, June, 1999.

Web servers

Page 4: PPT

4

Web servers

webserver

HTTP request

HTTP response(content)

webclient

(browser)

Page 5: PPT

5

• Web servers return content to clients

– content: a sequence of bytes with an

associated MIME (Multipurpose Internet Mail

Extensions) type

Web content

Page 6: PPT

6

• Example MIME types

– text/html HTML page

– text/plain Unformatted text

– application/postscript Postcript document

– image/gif Binary image encoded in GIF format

– image/jpg Binary image encoded in JPG format

Web content

Page 7: PPT

7

• The content returned in HTTP responses can be either static or dynamic– Static content:

• content stored in files and retrieved in response to an HTTP request

• Examples: HTML files, images, audio clips.

– Dynamic content: • content produced on-the-fly in response to an HTTP

request• Example: content produced by a program executed

by the server on behalf of the client.

Static and dynamic content

Page 8: PPT

8

• Each file managed by a server has a unique name called a URL (Universal Resource Locator)

• URLs for static content:– http://www.cs.cmu.edu:80/index.html– http://www.cs.cmu.edu/index.html– http://www.cs.cmu.edu

• identifies a file called index.html, managed by a Web server at www.cs.cmu.edu that is listening on port 80.

URLs

Page 9: PPT

9

• URLs for dynamic content:

– http://www.cs.cmu.edu:8000/cgi-bin/

adder?15000&213

• identifies an executable file called adder, managed

by a Web server at www.cs.cmu.edu that is listening

on port 8000, that should be called with two argument

strings: 15000 and 213.

URLs

Page 10: PPT

10

• Example URL:

http://www.aol.com:80/index.html

• Clients use prefix (http://www.aol.com:80)

to infer:

– What kind of server to contact (Web server)

– Where the server is (www.aol.com)

– What port it is listening on (80)

How clients and servers use URLs

Page 11: PPT

11

• Servers use suffix (/index.html) to:– Determine if request is for static or dynamic

content.• No hard and fast rules for this.

• Convention: executables reside in cgi-bin directory

– Find file on filesystem• Initial “/” in suffix denotes home directory for

requested content.

• Minimal suffix is “/”, which all servers expand to some default home page (e.g., index.html).

How clients and servers use URLs

Page 12: PPT

12

//Client: open connection to serverunix> telnet www.aol.com 80//Telnet prints 3 lines to the terminalTrying 205.188.146.23...Connected to aol.com.Escape character is '^]'.//Client: request lineGET / HTTP/1.1//Client: required HTTP/1.1 HOST headerhost: www.aol.com//Client: empty line terminates headers

Anatomy of an HTTP transaction

Page 13: PPT

13

//Server: response lineHTTP/1.0 200 OK//Server: followed by five response headersMIME-Version: 1.0Date: Mon, 08 Jan 2001 04:59:42 GMTServer: NaviServer/2.0 AOLserver/2.3.3//Server: expect HTML in the response body Content-Type: text/html//Server: expect 42,092 bytes in the resp bodyContent-Length: 42092//Server: empty line (“\r\n”) terminates hdrs

Anatomy of an HTTP transaction

Page 14: PPT

14

//Server: first HTML line in response body<html> ... //Server: 766 lines of HTML not shown.

</html>//Server: last HTML line in response body//Server: closes connection Connection closed by foreign host. Client: closes connection and terminates unix>

Anatomy of an HTTP transaction

Page 15: PPT

15

• Client sends request to server

• If request URI contains the string “/cgi-bin”,

then the server assumes that the request

is for dynamic content.

Serving dynamic content

client server

GET /cgi-bin/env.pl HTTP/1.1

Page 16: PPT

16

• The server creates a

child process and

runs the program

identified by the URI

in that process

client server

env.pl

fork/exec

Serving dynamic content

Page 17: PPT

17

• The child runs and generates the dynamic content.

• The server captures the content of the child and forwards it without modification to the client

client server

env.pl

content

content

Serving dynamic content

Page 18: PPT

18

• How does the client pass program

arguments to the server?

• How does the server pass these arguments

to the child?

• How does the server pass other info

relevant to the request to the child?

Serving dynamic content

Page 19: PPT

19

• How does the server capture the content

produced by the child?

• These issues are addressed by the

Common Gateway Interface (CGI)

specification.

Serving dynamic content

Page 20: PPT

20

Serving dynamic content

client server

content

content

request

create

env.pl

Page 21: PPT

21

• Question: – How does the client pass arguments to the

server?

• Answer: – The arguments are appended to the URI

• http://add.com/cgi-bin/adder?1&2• adder is the CGI program on the server that will do

the addition.• argument list starts with “?”• arguments separated by “&” • spaces represented by “%20”

Serving dynamic content

Page 22: PPT

22

• Question:

– How does the server pass these arguments to

the child?

• Answer:

– In environment variable QUERY_STRING

• a single string containing everything after the “?”

• for add.com: QUERY_STRING = “1&2”

Serving dynamic content

Page 23: PPT

23

Serving dynamic content

if ((buf = getenv("QUERY_STRING")) != NULL) {

p = strchr(buf, ’&’);

*p = ’\0’;

strcpy(arg1, buf);

strcpy(arg2, p+1);

n1 = atoi(arg1);

n2 = atoi(arg2);

}

Page 24: PPT

24

• Question:

– How does the server pass other info relevant to

the request to the child?

• Answer:

– in a collection of environment variables defined

by the CGI spec.

Serving dynamic content

Page 25: PPT

25

• Request-specific– QUERY_STRING (contains GET args)– SERVER_PORT

– REQUEST_METHOD (GET, POST, etc)– REMOTE_HOST (domain name of client)– REMOTE_ADDR (IP address of client)– CONTENT_TYPE (for POST, MIME type of the

request body )– CONTENT_LENGTH (for POST, length in bytes)

Some CGI environment variables

Page 26: PPT

26

• Question: – How does the server capture the content

produced by the child?

• Answer: – The child generates its output on stdout.

Server uses dup2 to redirect stdout to its connected socket.

– Notice that only the child knows the type and size of the content.

– Thus the child (not the server) must generate the corresponding headers.

Serving dynamic content

Page 27: PPT

27

/* Domain Name Service (DNS) host entry */struct hostent {/* official name of host */char *h_name; /* alias list */char **h_aliases; /* host address type */int h_addrtype; /* length of address */int h_length; /* list of addresses */char **h_addr_list;

}

Page 28: PPT

28

/* Internet address */struct in_addr { /* 32-bit IP address */ unsigned int s_addr;

};

/* Generic socket address structure(for connect, bind, and accept)

*/struct sockaddr {/* protocol family */unsigned short sa_family ;/* address data */char sa_data[14];

}

Page 29: PPT

29

/* Internet style socket address */struct sockaddr_in { /* Address family (AF_INET) */unsigned short sin_family; /* Port number */unsigned short sin_port; /* IP address */struct in_addr sin_addr;/* Pad to sizeof “struct sockaddr” */unsigned char sin_zero[8];

};

Page 30: PPT

30

struct hostent *genhostbyname(const char *name);

struct hostent *genhostbyaddr(const char *addr, int

len,0);

int socket(int domain, int type, int protocol);

clientfd = socekt(AF_INET,SOCKET_STREAM, 0) ;

int connect(int sockfd, struct sockaddr *serv_addr, int addr_len);

Page 31: PPT

31

int bind(int sockfd,

struct sockaddr *my_addr,

int addrlen);

int listen(int sockfd, int backlog) ;

int accept(int listenfd,

struct sockaddr *addr,

int addrlen) ;

Page 32: PPT

32

1 /*

2 * tiny.c - A simple HTTP/1.0 Web server that uses the GET method

3 * to serve static and dynamic content.

4 */

5 #include "csapp.h"

6

7 void doit(int fd);

8 void read_requesthdrs(int fd);

The Tiny Web Server

Page 33: PPT

33

9 int parse_uri(char *uri, char *filename, char

*cgiargs);

10 void serve_static(rio_t *rio, char *filename, int filesize);

11 void get_filetype(char *filename, char *filetype);

12 void serve_dynamic(rio_t *rio,char *filename,char*cgiargs);13 void clienterror(rio_t *rio, char *cause, char *errnum,

14 char *shortmsg, char *longmsg);

15

The Tiny Web Server

Page 34: PPT

34

16 int main(int argc, char **argv)17 {18 int listenfd, connfd, port, clientlen;19 struct sockaddr_in clientaddr;2021 /* check command line args */22 if (argc != 2) {23 fprintf(stderr,"usage: %s <port>\n", argv

[0]);24 exit(1);25 }26 port = atoi(argv[1]);27

The Tiny Web Server

Page 35: PPT

35

28 listenfd = open_listenfd(port);

29 while (1) {

30 clientlen = sizeof(clientaddr);

31 connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen);

32 doit(connfd);

33 Close(connfd);

34 }

35 }

The Tiny Web Server

Page 36: PPT

36

1 void doit(int fd)

2 {

3 int is_static;

4 struct stat sbuf;

5 char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];

6 char filename[MAXLINE], cgiargs[MAXLINE];

7 rio_t rio;

8

The Tiny Web Server

Page 37: PPT

37

9 /* read request line and headers */10 Rio_readinitb(&rio, fd)11 Rio_readlineb(&rio, buf, MAXLINE);12 sscanf(buf, "%s %s %s\n", method, uri, version);13 if (strcasecmp(method, "GET")) {14 clienterror(fd, method, "501", "Not

Implemented",15 "Tiny does not implement this method");16 return;17 }18 read_requesthdrs(&rio);19

The Tiny Web Server

Page 38: PPT

38

20 /* parse URI from GET request */21 is_static = parse_uri(uri, filename, cgiargs);22 if (stat(filename, &sbuf) < 0) {23 clienterror(fd, filename, "404", "Not found",24 "Tiny couldn’t find this file");25 return;26 }27

The Tiny Web Server

Page 39: PPT

39

28 if (is_static) { /* serve static content */29 if (!(S_ISREG(sbuf.st_mode)) ||

!(S_IRUSR & sbuf.st_mode)) {30 clienterror(fd, filename, "403", 31 "Forbidden","Tiny couldn’t read the

file");32 return;33 }34 serve_static(&rio, filename, sbuf.st_size);35 }

The Tiny Web Server

Page 40: PPT

40

34 else { /* serve dynamic content */35 if (!(S_ISREG(sbuf.st_mode)) ||

!(S_IXUSR & sbuf.st_mode)) {36 clienterror(fd, filename, "403", "Forbidden",37 "Tiny couldn’t run the CGI program");38 return;39 }40 serve_dynamic(&rio, filename, cgiargs);41 }42 }

The Tiny Web Server

Page 41: PPT

41

1 void clienterror(rio_t *fd, char *cause, char *errnum,2 char *shortmsg, char *longmsg)3 {4 char buf[MAXLINE], body[MAXBUF];56 /* build the HTTP response body */7 sprintf(body, "<html><title>Tiny Error</title>");8 sprintf(body, "%s<body bgcolor=""ffffff"">\r\n", body);9 sprintf(body, "%s%s: %s\r\n", body, errnum, shortmsg);10 sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause);11 sprintf(body, "%s<hr><em>The Tiny Web server</em>\r\n", body);1213 /* print the HTTP response */14 sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);15 Rio_writen(fd, buf, strlen(buf));16 sprintf(buf, "Content-type: text/html\r\n");17 Rio_writen(fd, buf, strlen(buf));18 sprintf(buf, "Content-length: %d\r\n\r\n", strlen(body));19 Rio_writen(fd, buf, strlen(buf));20 Rio_writen(fd, body, strlen(body));21 }

Page 42: PPT

42

1 void read_requesthdrs(rio_t *fd)2 {3 char buf[MAXLINE];45 Readline(fd, buf, MAXLINE);6 while(strcmp(buf, "\r\n"))7 Rio_readlineb(fd, buf, MAXLINE);8 return;9 }

The Tiny Web Server

Page 43: PPT

43

1 int parse_uri(char *uri, char *filename, char *cgiargs)2 {3 char *ptr;45 if (!strstr(uri, "cgi-bin")) { /* static content */6 strcpy(cgiargs, "");7 strcpy(filename, ".");8 strcat(filename, uri);9 if (uri[strlen(uri)-1] == ’/’)10 strcat(filename, "home.html");11 return 1;12 }13 else { /* dynamic content */14 ptr = index(uri, ’?’);15 if (ptr) {16 strcpy(cgiargs, ptr+1);17 *ptr = ’\0’;18 }19 else20 strcpy(cgiargs, "");21 strcpy(filename, ".");22 strcat(filename, uri);23 return 0;24 }25 }

Page 44: PPT

44

1 void serve_static(int fd, char *filename, int filesize)2 {3 int srcfd;4 char *srcp, filetype[MAXLINE], buf[MAXBUF];56 /* send response headers to client */7 get_filetype(filename, filetype);8 sprintf(buf, "HTTP/1.0 200 OK\r\n");9 sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);10 sprintf(buf, "%sContent-length: %d\n", buf, filesize);11 sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);12 Rio_writen(fd, buf, strlen(buf));1314 /* send response body to client */15 srcfd = Open(filename, O_RDONLY, 0);16 srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);17 Close(srcfd);18 Rio_writen(fd, srcp, filesize);19 Munmap(srcp, filesize);20 }21

Page 45: PPT

45

22 /*23 * get_filetype - derive file type from file name24 */25 void get_filetype(char *filename, char *filetype)26 {27 if (strstr(filename, ".html"))28 strcpy(filetype, "text/html");29 else if (strstr(filename, ".gif"))30 strcpy(filetype, "image/gif");31 else if (strstr(filename, ".jpg"))32 strcpy(filetype, "image/jpg");33 else34 strcpy(filetype, "text/plain");35 }

The Tiny Web Server

Page 46: PPT

46

The Tiny Web Server1 void serve_dynamic(int fd, char *filename, char *cgiargs)2 {3 char buf[MAXLINE];45 /* return first part of HTTP response */6 sprintf(buf, "HTTP/1.0 200 OK\r\n");7 Rio_writen(fd, buf, strlen(buf));8 sprintf(buf, "Server: Tiny Web Server\r\n");9 Rio_writen(fd, buf, strlen(buf));1011 if (Fork() == 0) { /* child */12 /* real server would set all CGI vars here */13 setenv("QUERY_STRING", cgiargs, 1);14 Dup2(fd, STDOUT_FILENO); /* redirect output to client*/15 Execve(filename, NULL, environ); /* run CGI program */16 }17 Wait(NULL); /* parent reaps child */18 }