Linux守护程序localhost可以工作,但不是实际的IP
这些天我正在学习APUE.2e(UNIX®环境中的高级编程,第二版),并且已经学习了第16章网络IPC:套接字。当我运行程序Linux守护程序localhost可以工作,但不是实际的IP,c,linux,sockets,service,daemon,C,Linux,Sockets,Service,Daemon,这些天我正在学习APUE.2e(UNIX®环境中的高级编程,第二版),并且已经学习了第16章网络IPC:套接字。当我运行程序ruptime(对于客户端)和ruptime(对于服务器端)时,发生了一些奇怪的事情。客户机程序显示一个客户机命令,该命令与服务器通信以从服务器获取输出 系统的uptime命令,服务器程序ruptimed(注意“d”)接收该命令,执行uptime命令,并将uptime的输出返回给客户端。两个程序编译正常,我将ruptime 4000/tcp添加到文件/etc/service
ruptime
(对于客户端)和ruptime
(对于服务器端)时,发生了一些奇怪的事情。客户机程序显示一个客户机命令,该命令与服务器通信以从服务器获取输出
系统的uptime
命令,服务器程序ruptimed
(注意“d”)接收该命令,执行uptime
命令,并将uptime
的输出返回给客户端。两个程序编译正常,我将ruptime 4000/tcp
添加到文件/etc/service
,这意味着服务ruptime
绑定到端口4000/tcp
。我在同一台机器(Ubuntu11.04)上运行了这两个程序,并首先运行了ruptimed
(当然):
输出是我所期望的。然而,当我跑步时:
$ ./ruptimed
$ ./ruptime 192.168.1.221
# the terminal blocks here
IP地址192.168.1.221是机器在内部网中的实际IP。这里怎么了?我搜索了互联网,发现它似乎需要/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
它也不起作用。ruptime
和ruptime
的源代码如下:
连接重试()
第三张唱片是我的发球时间。有什么不对劲吗?我不太了解它的含义。我不是C专家,但我知道一件事:您的守护进程可能只绑定到一个地址/接口,并且只接受来自它的连接 使用
netstat-nap
检查守护进程绑定到哪个地址
如果它正在侦听0.0.0.0
,则它正在接受来自每个接口的连接,包括本地主机
如果它正在侦听127.0.0.1
,它将只接受本地主机的请求
我打赌它只能绑定到
127.0.0.1
,这就是为什么你不能连接任何其他地址。这几乎肯定是防火墙问题,而不是编码问题。您可能希望查看并指定ufw线路上的端口或IP地址。+1,这是另一种可能性(除了netstat
或lsof-i
)@dj_segfult i禁用了ufw,但不起作用。PS:我可以通过ssh从另一台机器连接到该机器。@tlh1987我不使用ufw,但我相信你的话,你知道如何禁用防火墙。我会通过在服务器上运行WireShark来验证,看看当你的客户端发送数据包时,数据包是否到达了那里,但这就是我。但您可以通过ssh连接到计算机这一事实并不意味着什么,因为防火墙规则通常是特定于端口的。@dj_segfault是的,您是对的,防火墙规则是特定于端口的,ufw可以阻止我用于服务的端口4000,我已经对其进行了测试。我将命令netstat-nap的结果附加到问题的末尾。有什么不对吗?你是对的!谢谢你的帮助。我在/etc/hosts中将localhost更改为0.0.0.0,它可以工作。@tlh1987 mmm,我认为这不是修复它的正确方法,您应该更改服务器代码,使其绑定到每个接口(0.0.0.0)或所需的接口,并保持localhost/etc/hosts条目与以前一样(可能是127.0.0.1)。我不确定你应该放什么(我不是C语言的人),但我确定你必须改变initserver(SOCK_STREAM,aip->ai_addr,aip->ai_addrlen,QLEN)
从“服务器端”代码到initserver(SOCK_STREAM,'0.0.0',aip->ai_addrlen,QLEN)
或类似的东西。你好,我在同一本书中做同样的练习(仅第三版)。我对getaddrinfo(argv[1]、“ruptime”、&hint、&ailist)有问题!=0)
因为它找不到服务ruptime
它在如何创建此类服务的书中的哪里?
sudo ufw allow ruptime
// 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);
}
// 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 i.e. 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 i.e. 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);
}
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 -