我在閱讀「Unix網絡編程」第3版。書籍「Unix網絡編程」中的拒絕服務攻擊問題
我遇到6.8節的一個問題「TCP回聲服務器(再訪)」,在座的代碼如下:
#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 */
}
}
}
}
關於這個節目,作者說,服務器將從如下DDOS攻擊苦: enter image description here
該點一旦客戶端請求到來,服務器讀取整行然後回顯它。但是這個代碼,我們看到服務器使用Read函數從客戶端讀取數據,而不是ReadLine或Readn,在遇到'\ n'或者獲取指定大小的數據之前,後者不會返回,但是Read函數在這種情況下立即返回。 閱讀功能只是系統調用的包裝「讀」,如下:
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);
}
所以我感到困惑,爲什麼這個服務器將從DDoS攻擊受苦?
任何人都可以解釋它嗎?非常感謝你!
這個例子清楚地表明服務器是單線程的,讀操作是阻塞的。在讀完第一個字節後,服務器保持連接打開等待更多,但客戶端永遠不會發送它,因此服務器不可用於第二個客戶端。 –
此外,這不是DDoS攻擊,這只是一個簡單的DoS攻擊。 –
感謝詹姆斯的糾正。 –