550 likes | 700 Views
Chapter 3 & 4 Network Programming and Internet Applications. Topics. Network communication client-server computing communication paradigm an example application program interface an intuitive look at the API definition of the API code for an echo application code for a chat application
E N D
Chapter 3 & 4 Network Programming and Internet Applications
Topics • Network communication • client-server computing • communication paradigm • an example application program interface • an intuitive look at the API • definition of the API • code for an echo application • code for a chat application • code for a web application
Introduction • An important idea: A programmer can create Internet application software without understanding the underlying network technology or communication protocols. • The key: using libraries
Network Communication • Network: data transfer without interpreting them • Applications: data processing and exchange doing it in pairs, both must know data format and meaning, e.g., • one side: database services • another side: send requests
Client-Server computing • How the pairs know the location of each other? • Server: starts first and waits for the other application to contact it • Client: must know the location of the server and contact it.
Specify the server • The location of the server is given by a pair of identifiers: (computer, application) • The client can use alphabetic names as identifiers • The network only knows binary numbers • Network software does the translation
Communication paradigm Sequence of operations: • The server application starts first, and waits for contact from a client • The client contacts the server by specifying its location and requesting communication • The client and server exchange messages • After they finish sending data, the client and server each send an end-of-file to terminate communication
An example Application Program Interface (API) • API: the set of operations available to an application programmer • API specifies the arguments for each operation as well as the semantics
Definition of the API • Data types used
Functions defined by the API (1) • connection await_contact(appnum a) • connection make_contact(computer c, appnum a) • appnum appname_to_appnum(char *a) • computer cname_to_comp(char *c)
Functions defined by the API (2) • int send(connection con, char *buffer, int length, int flags) • con: The connection identifier *buffer: Data buffer length: Number of bytes to send. flag: 0 return: length if successful; negative otherwise
Functions defined by the API (3) • int recv(connection con, char *buffer, int length, int flags) • Block until data arrives. • con: The connection identifier *buffer: Data buffer length: Buffer size. return: # of bytes in the buffer; 0 if receives EOF; negative otherwise
Functions defined by the API (4) • int recvln(connection con, char *buffer, int length) • int send_eof(connection con)
Code for an echo application • Server: echoes back all the data it receives • Client: repeatedly does the following: • prompts the user for a line of input • sends the line to the server • displays whatever the server sends back
How to run the programs? • invoke the server: on computer cms07201.uhd.edu: > echoserver 20000 • invoke the client: > echoclient cms07201.uhd.edu
Example echo server code (1) /* echoserver.c */ #include <stdlib.h> #include <stdio.h> #include <cnaiapi.h> #define BUFFSIZE 256 /*------------------------------------------------------------ * * Program: echoserver * Purpose: wait for a connection from an echoclient and echo data * Usage: echoserver <appnum> * *------------------------------------------------------------ */
Example echo server code (2) int main(int argc, char *argv[]) { connection conn; int len; char buff[BUFFSIZE]; if (argc != 2) { (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]); exit(1); } /* wait for a connection from an echo client */ conn = await_contact((appnum) atoi(argv[1])); if (conn < 0) exit(1);
Example echo server code (3) /* iterate, echoing all data received until end of file */ while((len = recv(conn, buff, BUFFSIZE, 0)) > 0) (void) send(conn, buff, len, 0); send_eof(conn); return 0; }
Example echo client code (1) /* echoclient.c */ #include <stdlib.h> #include <stdio.h> #include <cnaiapi.h> #define BUFFSIZE 256 #define INPUT_PROMPT "Input > " #define RECEIVED_PROMPT "Received> " int readln(char *, int); /*------------------------------------------------------------ * * Program: echoclient * Purpose: contact echoserver, send user input and print server response * Usage: echoclient <compname> [appnum] * Note: Appnum is optional. If not specified the standard echo appnum * (7) is used. * *------------------------------------------------------------ */
Example echo client code (2) int main(int argc, char *argv[]) { computer comp; appnum app; connection conn; char buff[BUFFSIZE]; int expect, received, len; if (argc < 2 || argc > 3) { (void) fprintf(stderr, "usage: %s <compname> [appnum]\n", argv[0]); exit(1); } /* convert the arguments to binary format comp and appnum */ comp = cname_to_comp(argv[1]); if (comp == -1) exit(1);
Example echo client code (3) if (argc == 3) app = (appnum) atoi(argv[2]); else if ((app = appname_to_appnum("echo")) == -1) exit(1); /* form a connection with the echoserver */ conn = make_contact(comp, app); if (conn < 0) exit(1); (void) printf(INPUT_PROMPT); (void) fflush(stdout);
Example echo client code (4) /* iterate: read input from the user, send to the server, */ /* receive reply from the server, and display for user */ while((len = readln(buff, BUFFSIZE)) > 0) { /* send the input to the echoserver */ (void) send(conn, buff, len, 0); (void) printf(RECEIVED_PROMPT); (void) fflush(stdout);
Example echo client code (5) /* read and print same no. of bytes from echo server */ expect = len; for (received = 0; received < expect;) { len = recv(conn, buff, (expect - received) < BUFFSIZE ? (expect - received) : BUFFSIZE, 0); if (len < 0) { send_eof(conn); return 1; } (void) write(STDOUT_FILENO, buff, len); received += len; } (void) printf("\n"); (void) printf(INPUT_PROMPT); (void) fflush(stdout); }
Example echo client code (6) /* iteration ends when EOF found on stdin */ (void) send_eof(conn); (void) printf("\n"); return 0; }
Code for a chat application • A simplified version of chat: • works between a single pair of users • client and server take turns entering text; client starts • Both client and server enter a loop of reading and sending local user’s input and displaying the message from the other side • Both client and server proceed until they receive end-of-file
To run the aaplication • Server: chatserver 25000 • Client: chatclient cms70201.uhd.edu 25000
Example chat server code (1) /* chatserver.c */ #include <stdlib.h> #include <stdio.h> #include <cnaiapi.h> #define BUFFSIZE 256 #define INPUT_PROMPT "Input > " #define RECEIVED_PROMPT "Received> " int recvln(connection, char *, int); int readln(char *, int); /*------------------------------------------------------------ * * Program: chatserver * Purpose: wait for a connection from a chatclient & allow users to chat * Usage: chatserver <appnum> * *------------------------------------------------------------ */
Example chat server code (2) int main(int argc, char *argv[]) { connection conn; int len; char buff[BUFFSIZE]; if (argc != 2) { (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]); exit(1); } (void) printf("Chat Server Waiting For Connection.\n"); /* wait for a connection from a chatclient */ conn = await_contact((appnum) atoi(argv[1])); if (conn < 0) exit(1); (void) printf("Chat Connection Established.\n");
Example chat server code (3) /* iterate, reading from the client and the local user */ while((len = recvln(conn, buff, BUFFSIZE)) > 0) { (void) printf(RECEIVED_PROMPT); (void) fflush(stdout); (void) write(STDOUT_FILENO, buff, len); /* send a line to the chatclient */ (void) printf(INPUT_PROMPT); (void) fflush(stdout); if ((len = readln(buff, BUFFSIZE)) < 1) break; buff[len - 1] = '\n'; (void) send(conn, buff, len, 0); } /* iteration ends when EOF found on stdin or chat connection */ (void) send_eof(conn); (void) printf("\nChat Connection Closed.\n\n"); return 0; }
Example chat client code (1) /* chatclient.c */ #include <stdlib.h> #include <stdio.h> #include <cnaiapi.h> #define BUFFSIZE 256 #define INPUT_PROMPT "Input > " #define RECEIVED_PROMPT "Received> " int recvln(connection, char *, int); int readln(char *, int); /*------------------------------------------------------------ * * Program: chatclient * Purpose: contact a chatserver and allow users to chat * Usage: chatclient <compname> <appnum> * *------------------------------------------------------------ */
Example chat client code (2) int main(int argc, char *argv[]) { computer comp; connection conn; char buff[BUFFSIZE]; int len; if (argc != 3) { (void) fprintf(stderr, "usage: %s <compname> <appnum>\n", argv[0]); exit(1); } /* convert the compname to binary form comp */ comp = cname_to_comp(argv[1]); if (comp == -1) exit(1);
Example chat client code (3) /* make a connection to the chatserver */ conn = make_contact(comp, (appnum) atoi(argv[2])); if (conn < 0) exit(1); (void) printf("Chat Connection Established.\n"); (void) printf(INPUT_PROMPT); (void) fflush(stdout);
Example chat client code (4) /* iterate, reading from local user and then from chatserver */ while((len = readln(buff, BUFFSIZE)) > 0) { buff[len - 1] = '\n'; (void) send(conn, buff, len, 0); /* receive and print a line from the chatserver */ if ((len = recvln(conn, buff, BUFFSIZE)) < 1) break; (void) printf(RECEIVED_PROMPT); (void) fflush(stdout); (void) write(STDOUT_FILENO, buff, len); (void) printf(INPUT_PROMPT); (void) fflush(stdout); } /* iteration ends when stdin or the connection indicates EOF */ (void) printf("\nChat Connection Closed.\n"); (void) send_eof(conn); exit(0); }
Code for a web application Simplifications: • the server only supplies three web pages • none of the pages contains anything except text • pages are hard-wired into the code • the client does not format the web pages
Use standard protocol • The web server can communicate with a conventional web browser, e.g., enter the following in IE: http://cms70201.uhd.edu:27000/index.html • The web client can inter-operate with a commercial web server, e.g., webclient www.uhd.edu /
To run the applications • To run the server webserver 27000 • To run the client webclient cms70201.uhd.edu /index.html 27000
Example web client code (1) /* webclient.c */ #include <stdlib.h> #include <stdio.h> #include <cnaiapi.h> #define BUFFSIZE 256 /*------------------------------------------------------------ * * Program: webclient * Purpose: fetch page from webserver and dump to stdout with headers * Usage: webclient <compname> <path> [appnum] * Note: Appnum is optional. If not specified the standard www appnum (80) is used. * *------------------------------------------------------------ */
Example web client code (2) int main(int argc, char *argv[]) { computer comp; appnum app; connection conn; char buff[BUFFSIZE]; int len; if (argc < 3 || argc > 4) { (void) fprintf(stderr, "%s%s%s", "usage: ", argv[0], " <compane> <path> [appnum]\n"); exit(1); } /* convert arguments to binary computer and appnum */ comp = cname_to_comp(argv[1]); if (comp == -1) exit(1);
Example web client code (3) if (argc == 4) app = (appnum) atoi(argv[3]); else if ((app = appname_to_appnum("www")) == -1) exit(1); /* contact the web server */ conn = make_contact(comp, app); if (conn < 0) exit(1); /* send an HTTP/1.0 request to the webserver */ len = sprintf(buff, "GET %s HTTP/1.0\r\n\r\n", argv[2]); (void) send(conn, buff, len, 0);
Example web client code (4) /* dump all data received from the server to stdout */ while((len = recv(conn, buff, BUFFSIZE, 0)) > 0) (void) write(STDOUT_FILENO, buff, len); return 0; }
Example web server code (1) /* webserver.c */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <cnaiapi.h> #if defined(LINUX) || defined(SOLARIS) #include <sys/time.h> #endif #define BUFFSIZE 256 #define SERVER_NAME "CNAI Demo Web Server" #define ERROR_400 "<head></head><body><html><h1>Error 400</h1><p>The server couldn't understand your request.</html></body>\n" #define ERROR_404 "<head></head><body><html><h1>Error 404</h1><p>Do\ cument not found.</html></body>\n"
Example web server code (2) #define HOME_PAGE "<head></head><body><html><h1>Welcome to the CNAI Demo Server</h1><p>Why not visit: <ul><li><a href=\"http://netbook.cs.purdue.edu\">Netbook Home Page</a><li><a href=\"http://www.comerbooks.com\">Comer Books Home Page<a></ul></html></body>\n" #define TIME_PAGE "<head></head><body><html><h1>The current date is: %s</h1></html></body>\n" int recvln(connection, char *, int); void send_head(connection, int, int); /*------------------------------------------------------------ * * Program: webserver * Purpose: serve hard-coded webpages to web clients * Usage: webserver <appnum> * *------------------------------------------------------------ */
Example web server code (3) int main(int argc, char *argv[]) { connection conn; int n; char buff[BUFFSIZE], cmd[16], path[64], vers[16]; char *timestr; #if defined(LINUX) || defined(SOLARIS) struct timeval tv; #elif defined(WIN32) time_t tv; #endif if (argc != 2) { (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]); exit(1); }
Example web server code (4) while(1) { /* wait for contact from a client on specified appnum */ conn = await_contact((appnum) atoi(argv[1])); if (conn < 0) exit(1); /* read and parse the request line */ n = recvln(conn, buff, BUFFSIZE); sscanf(buff, "%s %s %s", cmd, path, vers); /* skip all headers - read until we get \r\n alone */ while((n = recvln(conn, buff, BUFFSIZE)) > 0) { if (n == 2 && buff[0] == '\r' && buff[1] == '\n') break; }
Example web server code (5) /* check for unexpected end of file */ if (n < 1) { (void) send_eof(conn); continue; } /* check for a request that we cannot understand */ if (strcmp(cmd, "GET") || (strcmp(vers, "HTTP/1.0") && strcmp(vers, "HTTP/1.1"))) { send_head(conn, 400, strlen(ERROR_400)); (void) send(conn, ERROR_400, strlen(ERROR_400),0); (void) send_eof(conn); continue; }
Example web server code (6) /* send the requested web page or a "not found" error */ if (strcmp(path, "/") == 0) { send_head(conn, 200, strlen(HOME_PAGE)); (void) send(conn, HOME_PAGE, strlen(HOME_PAGE),0); } else if (strcmp(path, "/time") == 0) { #if defined(LINUX) || defined(SOLARIS) gettimeofday(&tv, NULL); timestr = ctime(&tv.tv_sec); #elif defined(WIN32) time(&tv); timestr = ctime(&tv); #endif (void) sprintf(buff, TIME_PAGE, timestr); send_head(conn, 200, strlen(buff)); (void) send(conn, buff, strlen(buff), 0); } else { /* not found */ send_head(conn, 404, strlen(ERROR_404)); (void) send(conn, ERROR_404, strlen(ERROR_404),0); } (void) send_eof(conn); } }