Transcript ppt

15-213 Recitation 10 – 4/22/01
Outline
• File I/O
• Networking
Reminders
• Lab 6: Dynamic Memory
Allocator
• Lab Due 4/22
e-mail:
[email protected]
Office Hours:
See Web for times and
locations
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 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;
•
•
/* 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);
}
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 close the
connection
– Create a socket()
– Connect()
– Write()/read()
– Close()
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 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);
}
Networking: Server Code: Main Loop
/*** Code to setup allSet, which contains all the sockets we need ***/
while(1){
readSet=allSet;
numReadyDescriptors=select(maxfd+1,&readSet,NULL,NULL,NULL);
if(FD_ISSET(udpSocketfd,&readSet)){
/* Packet arrived on UDP Socket: Must be chat message: Process it */
ProcessIncomingChatMessage(udpSocketfd);
numReadyDescriptors--;
if(numReadyDescriptors <= 0) continue;
}
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;
}
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