15 213 Recitation 10 42202 Outline File IO

  • Slides: 13
Download presentation
15 -213 Recitation 10 – 4/22/02 Outline • File I/O • Networking James Wilson

15 -213 Recitation 10 – 4/22/02 Outline • File I/O • Networking James Wilson e-mail: wilson 2@andrew. cmu. edu Office Hours: Friday 1: 30 – 3: 00 Today 6 -8 pm Reminders • Lab 6: Dynamic Memory Allocator • Lab Due 4/22 Wean 520 X

Unix I/O vs. Standard I/O • Standard I/O almost always preferred • Standard I/O

Unix I/O vs. Standard I/O • Standard I/O almost always preferred • Standard I/O a higher-level abstraction than UNIX I/O • Standard I/O models files as a stream, like file descriptors in being full-duplex • Restrictions exist that interact badly with restrictions on sockets • Input function cannot follow an output function (or vise versa) without a call to fflush, fseek, fsetpos, rewind, or and end-of-file

Logging and Network I/O • Have a server set up to receive requests and

Logging and Network I/O • Have a server set up to receive requests and respond to them. • Read in request, parse, and return response. • Need to read/write to a network stream, and log events to a file for record-keeping purposes • Main loop opens file for logging and spawns children threads • Each thread has own network streams, but shares logging file stream • Use of mutex to lock resources glossed over for now (will be covered in detail)

Reading to/from Network & File • • • void main () { FILE* log;

Reading to/from Network & File • • • void main () { FILE* log; • • /* open file */ log = fopen ( "log. txt“, "a“ ); • • • while ( true ) { /* * Main Loop (inside thread) */ } • • fclose ( log ); }

Reading to/from Network & File • • • void *thread ( void *vargp )

Reading to/from Network & File • • • void *thread ( void *vargp ) { FILE* stream; char method[BUFSIZE], uri[BUFSIZE], version[BUFSIZE]; /* create mutex */ • • • /* given argument, set file descriptor for proper access to streams */ childfd = *((int *)vargp); free(vargp); • • /* open file descriptors for reading network socket, set buffer type */ if ((stream = fdopen(childfd, "r+")) == NULL) error("ERROR on fdopen"); setvbuf(stream, NULL, _IONBF, 0); • • • /* get header off the stream and save */ fgets(buf, BUFSIZE, stream); sscanf(buf, "%s %s %sn", method, uri, version);

Reading to/from Network & File • • • /* * Parse, error check, ready

Reading to/from Network & File • • • /* * Parse, error check, ready for server communication. */ • • • /* * determine size of information to be written back * in this case, copying from some other stream (buf) * to the network stream (stream) */ • • • /* get size of remaining buffer from stream */ temp = read ( serverfd, buf, BUFSIZE ); while ( temp > 0 ) { data. byte += temp; /* * write current buffered amount to network socket * get size of remaining buffer from stream */ fwrite ( buf, sizeof ( char ), temp, stream ); temp = read ( serverfd, buf, BUFSIZE ); }

Reading to/from Network & File • • /** init mutex **/ /** lock mutex

Reading to/from Network & File • • /** init mutex **/ /** lock mutex **/ /* write to log file */ fprintf(log, "%s %s %s %dn", data. date, data. ip, data. address, data. byte); /** unlock mutex **/ /* close network buffer */ fclose(stream); }

Networking • Two sides to networking – Client / Server – Distinction is fading

Networking • Two sides to networking – Client / Server – Distinction is fading • Peer-to-peer systems mean a node is both

Networking: Client Code Path • Clients typically connect to servers, perform a task, then

Networking: Client Code Path • Clients typically connect to servers, perform a task, then close the connection – Create a socket() – Connect() – Write()/read() – Close()

Networking: Server Code Path • Servers wait for connections and handle them as they

Networking: Server Code Path • Servers wait for connections and handle them as they arrive – – – – Create a socket() Bind() to a port Listen() for connections Accept() a connection Select() a ready connection Read()/Write() Close() the connection • We’ll focus on TCP, but UDP is just as important

Networking: Server Code: Initialization void Create. TCPServer(){ struct sockaddr_in my. Addr; int my. Addr.

Networking: Server Code: Initialization void Create. TCPServer(){ struct sockaddr_in my. Addr; int my. Addr. Len; int reuse. Addr. Flg=1; tcp. Socketfd=socket(AF_INET, SOCK_STREAM, 0); bzero((void *)(&my. Addr), sizeof(my. Addr)); my. Addr. sin_family=AF_INET; my. Addr. sin_port= htons((unsigned short)atoi(chat. TCPServer. Port)); my. Addr. sin_addr. s_addr=htonl(INADDR_ANY); setsockopt(tcp. Socketfd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse. Addr. Flg, sizeof(reuse. Addr. Flg)); bind(tcp. Socketfd, (struct sockaddr *)&my. Addr, sizeof(my. Addr)); listen(tcp. Socketfd, MAX_BACKLOG); }

Networking: Server Code: Main Loop /*** Code to setup all. Set, which contains all

Networking: Server Code: Main Loop /*** Code to setup all. Set, which contains all the sockets we need ***/ while(1){ read. Set=all. Set; num. Ready. Descriptors=select(maxfd+1, &read. Set, NULL, NULL); if(FD_ISSET(udp. Socketfd, &read. Set)){ /* Packet arrived on UDP Socket: Must be chat message: Process it */ Process. Incoming. Chat. Message(udp. Socketfd); num. Ready. Descriptors--; if(num. Ready. Descriptors <= 0) continue; } if(FD_ISSET(tcp. Socketfd, &read. Set)){ /* Incoming request for new connection */ struct sockaddr_in client. Addr; int client. Addr. Len; slavefd=accept(tcp. Socketfd, (struct sockaddr *)&client. Addr, &client. Addr. Len) ; /*** Save slavefd so we know to check it later ***/ FD_SET(slavefd, &all. Set); if(slavefd > maxfd) maxfd=slavefd; fflush(stdout); num. Ready. Descriptors--; if(num. Ready. Descriptors <= 0) continue; }

Networking: Server Code: The Rest • Check whether interesting socket descriptors are in the

Networking: Server Code: The Rest • Check whether interesting socket descriptors are in the read/write set • Do appropriate action if they are (i. e. , read() or write()) • Close() the connection when appropriate