I'm reading "Unix Networking Programming" the 3ed edition.
I encounter a question in 6.8 section "TCP Echo Server (Revisited)", here present code as below:
#include "unp.h"
int
main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
**if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
/*4connection closed by client */
Close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else
Writen(sockfd, buf, n);**
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
About this program, Author said the server will suffer from DDOS attack as below: enter image description here
the point is once a client request come, server read entire line then echo it. But is this code, we see server use Read function read data from client, not ReadLine or Readn, latters won't return until encounter a '\n' or fetch specified size data, but Read function immediately return in this case. Read function just wrapper of system call "read" as below:
ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = read(fd, ptr, nbytes)) == -1)
err_sys("read error");
return(n);
}
So I confused why this server will suffer from a ddos attack?
Anyone can clarify it? Thank you very much!
I think that the confusion is due to a possible difference between the second edition and third edition of the book.
I have the 2nd edition and in it the "Read" is actually a "Readline". Then the explanation makes sense, due to the fact that Readline insists on reading until a newline.
I do not have a copy of the 3rd edition to compare with.
As for the explanation from Drunken Code Monkey, true, the read is blocking, however it is protected by the select which will guarantee that the read is only called if there is activity on the socket (either a disconnect, or at least 1 byte to read). So it is guaranteed that the read will not block. But see my explanation regarding if Read is replaced with Readline (as in 2nd edition)
See also a previous post on Stack Overflow Unix Network Programming Clarification