Linux守护进程localhost工作,但不是实际的IP

我正在学习APUE.2e(UNIX®环境下的高级编程,第二版),并且涉及到第16章networkingIPC:套接字。 当我运行程序ruptime (用于客户端)和ruptimed (用于服务器端)时,发生了一些奇怪的事情。 客户端程序显示一个客户端命令,与服务器进行通信以从系统的uptime命令获得输出,服务器程序ruptimed (注意'd')接收命令,exec的uptime命令并将uptime的输出返回给客户。 这两个程序编译成OK,并且将ruptime 4000/tcp添加到文件/etc/service ,这意味着服务ruptime绑定到端口4000/tcp 。 我在同一台机器上运行了两个程序(Ubuntu 11.04),第一个(当然):

 $ ./ruptimed $ ./ruptime 127.0.0.1 21:35:48 up 13:06, 3 users, load average: 0.56, 0.85, 0.94 

输出是我所期望的。 但是,当我跑时:

 $ ./ruptimed $ ./ruptime 192.168.1.221 # the terminal blocks here 

IP地址192.168.1.221是内网中机器的实际IP地址。 这里有什么问题? 我search了互联网,发现它似乎需要/etc/init.d/中的一个shell脚本。 然后我在/etc/init.d/目录下添加一个名为ruptime的文件。 这里是:

 #! /bin/sh ### BEGIN INIT INFO # Provides: ruptimed # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: # Short-Description: ruptime ### END INIT INFO start() { echo "start ruptime" /home/tlh1987/apue-practice/tlh-practice/ruptimed exit 0; } stop() { killall ruptimed echo "stop ruptime" } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo "usage: $0 start|stop|restart" exit 0; esac 

然而,这不起作用,我不知道为什么。 我也设置ufw启用,并允许像这样的ruptime:

 sudo ufw allow ruptime 

它也没有工作。 ruptimeruptimed的源代码如下:

connect_retry()

 // the functions used in the two program // the connect_retry() function #include "apue.h" #include <sys/socket.h> #define MAXSLEEP 128 int connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen) { int nsec; for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) { if (connect(sockfd, addr, alen) == 0) { return (0); } if (nsec <= MAXSLEEP/2) sleep(nsec); } return (-1); } 

init_server()

 // the initserver function #include "apue.h" #include <errno.h> #include <sys/socket.h> int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen) { int fd; int err = 0; if ((fd = socket(addr->sa_family, type, 0)) < 0) return (-1); if (bind(fd, addr, alen) < 0) { err = errno; goto errout; } if (type == SOCK_STREAM || type == SOCK_SEQPACKET) { if (listen(fd, qlen) < 0) { err = errno; goto errout; } } return(fd); errout: close(fd); errno = err; return (-1); } 

客户端

 // the client end ie ruptime.c #include "apue.h" #include <netdb.h> #include <errno.h> #include <sys/socket.h> #define MAXADDRLEN 256 #define BUFLEN 128 extern int connect_retry(int, const struct sockaddr *, socklen_t); void print_uptime(int sockfd) { int n; char buf[BUFLEN]; while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0) write(STDOUT_FILENO, buf, n); if (n < 0) err_sys("recv error"); } int main(int argc, char *argv[]) { struct addrinfo *ailist, *aip; struct addrinfo hint; int sockfd, err; if (argc !=2 ) err_quit("usage: ruptime hostname"); hint.ai_flags = 0; 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(argv[1], "ruptime", &hint, &ailist)) != 0) err_quit("getaddrinfo error: %s", gai_strerror(err)); for (aip = ailist; aip != NULL; aip = aip->ai_next) { if ((sockfd = socket(aip->ai_family, SOCK_STREAM, 0)) < 0) err = errno; if (connect_retry(sockfd, aip->ai_addr, aip->ai_addrlen) < 0) { err = errno; } else { print_uptime(sockfd); exit(0); } } fprintf(stderr, "can't connect to %s: %s\n", argv[1], strerror(err)); exit(1); } 

服务器端

 //the server end ie ruptimed is as follows: #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 extern int initserver(int, struct sockaddr *, socklen_t, int); void serve(int sockfd) { int clfd; FILE *fp; char buf[BUFLEN]; for ( ; ; ) { clfd = accept(sockfd, NULL, NULL); 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; if (argc != 1) err_quit("usage: ruptimed"); #ifdef _SC_HOST_NAME_MAX n = sysconf(_SC_HOST_NAME_MAX); if (n < 0) #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"); 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) serve(sockfd); exit(0); } exit(1); } 

有没有人可以帮忙?

命令的标题行netstat -nap:

 Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:4000 0.0.0.0:* LISTEN 2252/ruptimed tcp 0 13033 192.168.1.221:47380 91.189.89.114:443 LAST_ACK - tcp 74 0 192.168.1.221:43914 91.189.89.76:443 ESTABLISHED 1846/python tcp 0 0 127.0.0.1:4000 127.0.0.1:56344 TIME_WAIT - tcp 0 1 192.168.1.221:35442 192.168.1.89:24800 SYN_SENT 1478/synergyc tcp 0 0 192.168.1.221:34957 74.125.71.125:5222 ESTABLISHED 1618/chrome tcp 0 0 192.168.1.221:57795 203.208.46.163:443 ESTABLISHED 1618/chrome tcp6 0 0 :::22 :::* LISTEN - 

第三个logging是我的服务ruptime。 这是错的吗? 我不太了解它的意思。

我不是C专家,但是我知道一件事情:守护进程可能只绑定到一个地址/接口,并且只接受来自它的连接。

使用netstat -nap检查守护进程绑定到哪个地址。

如果它正在侦听0.0.0.0那么它正在接受来自每个接口(包括本地主机)的连接。

如果它正在监听127.0.0.1它只会从本地主机接受。

我敢打赌,它只能绑定到127.0.0.1 ,这就是为什么你不能连接任何其他地址。

这几乎肯定是防火墙问题,而不是编码问题。 您可能需要查看一些ufw文档,并在ufw行上指定端口或IP地址。