Transcript ppt
15-213 Recitation 9
Greg Reshko
Office Hours: Wed 2:00-3:00PM
April 21st, 2003
Outline
File I/O
Networking
Lab 7
Unix File I/O
All I/O devices are modeled as files
Networks, disks, terminals, etc
All input and output is performed by reading and
writing the appropriate files
Kernel maintains all information about files and just
returns a file descriptor to an application that wants
access to a given file
Unix File I/O: Read/Write
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
Unix File I/O: More Robust
Robust I/O (RIO) Package:
Unbuffered:
ssize_t readn(int fd, void *buf, size_t count);
ssize_t writen(int fd, const void *buf, size_t count);
ssize_t readline(int fd, void *buf, size_t maxlen);
Buffered (thread-safe):
ssize_t readnb(int fd, void *buf, size_t count);
ssize_t writenb(int fd, const void *buf, size_t count);
ssize_t readlineb(int fd, void *buf, size_t maxlen);
Standard I/O vs. Unix I/O
Standard I/O almost always preferred
fopen, fclose, fseek, fread, fwrite, fscanf,
fprintf, etc.
A higher-level abstraction than UNIX I/O
Models files as streams, like file descriptors in being
full-duplex
Restrictions exist that interact badly with restrictions
on sockets
Input function cannot follow an output function (or vice versa)
without a call to fflush, fseek, fsetpos, rewind, or and
end-of-file
Networking
Two sides to networking
Client
/ Server
Distinction is fading
Peer-to-peer systems mean a node is both
Client Code Path
Clients typically connect to servers,
perform a task, then close the
connection
Create
a socket()
Connect()
Write()/read()
Close()
Server Code Path
Servers wait for connections and handle them
as they arrive
Create a socket()
Bind() to a port
Listen() for connections
Select() a ready connection
Accept() a connection
Read()/Write()
Close()
the connection
We’ll focus on TCP, but UDP is just as
important
Server: Init
void CreateTCPServer()
{
struct sockaddr_in myAddr;
int myAddrLen;
int reuseAddrFlg=1;
tcpSocketfd = socket(AF_INET,SOCK_STREAM,0);
bzero((void *)(&myAddr),sizeof(myAddr));
myAddr.sin_family = AF_INET;
myAddr.sin_port = htons((unsigned short)atoi(chatTCPServerPort));
myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
setsockopt(tcpSocketfd,SOL_SOCKET,SO_REUSEADDR,(void *)
&reuseAddrFlg,sizeof(reuseAddrFlg));
bind(tcpSocketfd,(struct sockaddr *)&myAddr,sizeof(myAddr));
listen(tcpSocketfd,MAX_BACKLOG);
}
Server: Loop
while(1)
{
readSet=allSet;
numReadyDescriptors=select(maxfd+1,&readSet,NULL,NULL,NULL);
if(FD_ISSET(tcpSocketfd,&readSet))
{
/* Incoming request for new connection */
struct sockaddr_in clientAddr;
int clientAddrLen;
slavefd=accept(tcpSocketfd,(struct sockaddr *) &clientAddr,
&clientAddrLen);
/* Save slavefd so we know to check it later */
FD_SET(slavefd,&allSet);
if(slavefd > maxfd) maxfd=slavefd;
fflush(stdout);
numReadyDescriptors--;
if(numReadyDescriptors <= 0)
continue;
}
}
Server: 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
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
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 )
{
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 %s\n", method, uri, version);
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 **/
/* write to log file */
fprintf(log, "%s %s %s %d\n", data.date, data.ip, data.address, data.byte);
/** unlock mutex **/
/* close network buffer */
fclose(stream);
}
Lab 7 – Logging Web Proxy
Start early (yeah, that’s a new one…)
Read the book carefully
Everything
you need for this lab is in the
book – make sure you understand it
Concurrency issues
Test it with your web browser
i.e.
Internet Explorer
This is the coolest part of the lab