#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <sys/socket.h>
#define BUFLEN 128
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif
fd_set allset;
int servers[FD_SETSIZE];
int maxi = -1;
extern int initserver(int, struct sockaddr *, socklen_t, int);
void
serve(int maxfd)
{
int i = 0, clfd, sockfd, nready = 0;
FILE *fp;
char buf[BUFLEN];
fd_set readset;
FD_ZERO(&readset);
for (;;) {
readset = allset;
nready = select(maxfd + 1, &readset, NULL, NULL, NULL);
if (nready < 0)
{
syslog(LOG_ERR, "ruptimed: select error: %s",
strerror(errno));
exit(1);
}
for (i = 0; i <= maxi; i++)
{
sockfd = servers[i];
if (FD_ISSET(sockfd, &readset))
{
clfd = accept(sockfd, NULL, NULL);
if (clfd < 0)
}
if (clfd < 0) {
syslog(LOG_ERR, "ruptimed: accept error: %s",
strerror(errno));
exit(1);
}
if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
sprintf(buf, "error: %s\n", strerror(errno));
send(clfd, buf, strlen(buf), 0);
} else {
while (fgets(buf, BUFLEN, fp) != NULL)
send(clfd, buf, strlen(buf), 0);
pclose(fp);
}
close(clfd);
}
}
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err, n;
char *host;
char *addr, abuf[INET_ADDRSTRLEN];
struct sockaddr_in *sinp;
int i = 0, maxfd = -1;
if (argc != 1)
err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
n = sysconf(_SC_HOST_NAME_MAX);
if (n < 0) /* best guess */
#endif
n = HOST_NAME_MAX;
host = malloc(n);
if (host == NULL)
err_sys("malloc error");
if (gethostname(host, n) < 0)
err_sys("gethostname error");
daemonize("ruptimed");
for (i = 0; i < FD_SETSIZE; i++)
servers[i] = -1;
FD_ZERO(&allset);
hint.ai_flags = AI_CANONNAME;
hint.ai_family = 0;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
gai_strerror(err));
exit(1);
}
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if (( sockfd = initserver(SOCK_STREAM, aip->ai_addr,
aip->ai_addrlen, QLEN)) >= 0) {
sinp = (struct sockaddr_in *)aip->ai_addr;
addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
syslog(LOG_INFO, "canonname: %s, address: %s, port: %d", aip->ai_canonname,
addr, ntohs(sinp->sin_port));
for (i = 0; i < FD_SETSIZE; i++) {
if (servers[i] < 0) {
servers[i] = sockfd;
if (i > maxi)
maxi = i;
break;
}
}
if (maxfd < sockfd)
maxfd = sockfd;
FD_SET(sockfd, &allset);
}
}
if (maxfd >= 0)
serve(maxfd);
else
exit(1);
exit(0);
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <sys/socket.h>
#define BUFLEN 128
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif
fd_set allset;
int servers[FD_SETSIZE];
int maxi = -1;
extern int initserver(int, struct sockaddr *, socklen_t, int);
void
serve(int maxfd)
{
int i = 0, clfd, sockfd, nready = 0;
FILE *fp;
char buf[BUFLEN];
fd_set readset;
FD_ZERO(&readset);
for (;;) {
readset = allset;
nready = select(maxfd + 1, &readset, NULL, NULL, NULL);
if (nready < 0)
{
syslog(LOG_ERR, "ruptimed: select error: %s",
strerror(errno));
exit(1);
}
for (i = 0; i <= maxi; i++)
{
sockfd = servers[i];
if (FD_ISSET(sockfd, &readset))
{
clfd = accept(sockfd, NULL, NULL);
if (clfd < 0)
continue;
break;
}
if (clfd < 0) {
syslog(LOG_ERR, "ruptimed: accept error: %s",
strerror(errno));
exit(1);
}
if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
sprintf(buf, "error: %s\n", strerror(errno));
send(clfd, buf, strlen(buf), 0);
} else {
while (fgets(buf, BUFLEN, fp) != NULL)
send(clfd, buf, strlen(buf), 0);
pclose(fp);
}
close(clfd);
}
}
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err, n;
char *host;
char *addr, abuf[INET_ADDRSTRLEN];
struct sockaddr_in *sinp;
int i = 0, maxfd = -1;
if (argc != 1)
err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
n = sysconf(_SC_HOST_NAME_MAX);
if (n < 0) /* best guess */
#endif
n = HOST_NAME_MAX;
host = malloc(n);
if (host == NULL)
err_sys("malloc error");
if (gethostname(host, n) < 0)
err_sys("gethostname error");
daemonize("ruptimed");
for (i = 0; i < FD_SETSIZE; i++)
servers[i] = -1;
FD_ZERO(&allset);
hint.ai_flags = AI_CANONNAME;
hint.ai_family = 0;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
gai_strerror(err));
exit(1);
}
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if (( sockfd = initserver(SOCK_STREAM, aip->ai_addr,
aip->ai_addrlen, QLEN)) >= 0) {
sinp = (struct sockaddr_in *)aip->ai_addr;
addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
syslog(LOG_INFO, "canonname: %s, address: %s, port: %d", aip->ai_canonname,
addr, ntohs(sinp->sin_port));
for (i = 0; i < FD_SETSIZE; i++) {
if (servers[i] < 0) {
servers[i] = sockfd;
if (i > maxi)
maxi = i;
break;
}
}
if (maxfd < sockfd)
maxfd = sockfd;
FD_SET(sockfd, &allset);
}
}
if (maxfd >= 0)
serve(maxfd);
else
exit(1);
exit(0);
}
main函数中红色部分对getaddrinfo返回的addrinfo链表中的端点依次调用initserver使其处于监听状态,使用servers数组中的第一个未用项记录这个监听描述符,maxi记录servers数组当前使用的最大下标,maxfd记录每个监听描述符中的最大值(+1后为select的第一个参数)。最后将每个监听描述符加入描述符集合allset中。
serve函数中红色部分将readset复制为allset的副本,然后调用select对readset集合进行监听(注意select函数中readset为值-结果参数,函数返回时集合内任何未就绪描述符对应的位返回时均清0,因此每次调用select前,都要把readset重新赋值为allset);接下来的for循环检查哪个监听描述符已就绪,对已就绪的监听描述符调用Accept接受用户连接请求,并使用返回的已连接描述符为客户服务。
查看监听状态:
netstat -antp | grep "ruptimed"