Originally Posted by
anduril462
Nope, continue only works on the innermost loop. Thus, you are continuing the read/write loop, not the listen/accept loop.
Ok, I'm back looking at the book and it appears as if Salem
has out-boffined the boffins who wrote it.
This is the server code from the book (p93 of pdf version).
Code:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#define SERVERPORT 8888
#define MAXBUF 1024
int main()
{
int socket1,socket2;
int addrlen;
struct sockaddr_in xferServer, xferClient;
int returnStatus;
/* create a socket */
socket1 = socket(AF_INET, SOCK_STREAM, 0);
if (socket1 == -1)
{
fprintf(stderr, "Could not create socket!\n");
exit(1);
}
/* bind to a socket, use INADDR_ANY for all local addresses */
xferServer.sin_family = AF_INET;
xferServer.sin_addr.s_addr = INADDR_ANY;
xferServer.sin_port = htons(SERVERPORT);
returnStatus = bind(socket1,(struct sockaddr*)&xferServer,sizeof(xferServer));
if (returnStatus == -1)
{
fprintf(stderr, "Could not bind to socket!\n");
exit(1);
}
returnStatus = listen(socket1, 5);
if (returnStatus == -1)
{
fprintf(stderr, "Could not listen on socket!\n");
exit(1);
}
for(;;)
{
int fd;
int i, readCounter, writeCounter;
char* bufptr;
char buf[MAXBUF];
char filename[MAXBUF];
/* wait for an incoming connection */
addrlen = sizeof(xferClient);
/* use accept() to handle incoming connection requests */
/* and free up the original socket for other requests */
socket2 = accept(socket1, (struct sockaddr*)&xferClient, &addrlen);
if (socket2 == -1)
{
fprintf(stderr, "Could not accept connection!\n");
exit(1);
}
/* get the filename from the client over the socket */
i = 0;
if ((readCounter = read(socket2, filename + i, MAXBUF)) > 0)
{
i += readCounter;
}
if (readCounter == -1)
{
fprintf(stderr, "Could not read filename from socket!\n");
close(socket2);
continue;
}
filename[i+1] = '\0';
printf("Reading file %s\n", filename);
/* open the file for reading */
fd = open(filename, O_RDONLY);
if (fd == -1)
{
close(socket2);
continue;
}
/* reset the read counter */
readCounter = 0;
/* read the file, and send it to the client in chunks of size MAXBUF */
while((readCounter = read(fd, buf, MAXBUF)) > 0)
{
writeCounter = 0;
bufptr = buf;
while (writeCounter < readCounter)
{
readCounter -= writeCounter;
bufptr += writeCounter;
writeCounter = write(socket2, bufptr, readCounter);
if (writeCounter == -1)
{
fprintf(stderr, "Could not write file to client!\n");
close(socket2);
continue;
}
}
}
close(fd);
close(socket2);
}
close (socket1);
return 0;
}
Offhand I'm thinking the code needs an error flag set then a break in the innermost loop,
then a check for the flag and a break if found in the next loop so it then returns
to listening mode after closing both the file and redundant socket.
Code:
int errflag = 0;
while((readCounter = read(fd, buf, MAXBUF)) > 0)
{
writeCounter = 0;
bufptr = buf;
while (writeCounter < readCounter)
{
readCounter -= writeCounter;
bufptr += writeCounter;
writeCounter = write(socket2, bufptr, readCounter);
if (writeCounter == -1)
{
fprintf(stderr, "Could not write file to client!\n");
errflag = 1;
break;
}
}
if(errflag == 1)
{
break;
}
}
Apart from that I'm left thinking its pretty hard to check that the
less travelled pathways do in fact do what's intended.