1 因特网守护进程xinetd
Xinetd(extended internet daemon),是新一代的网络守护进程服务程序,又叫超级Internet服务器,常用来管理多种轻量级Internet服务。Xinetd同时监听许多端口上的连接,当客户连接到某项服务时,守护程序就运行相应的服务器,这使得针对各项网络服务的服务器不需要一直运行,它们可以在需要时启动。
1.1 配置
Xinetd的配置文件是/etc/xinetd.conf
,但是它只包括默认值,并包含/etc/xinetd.d
目录中的配置文件。每一个由xinetd提供的服务都在/etc/xinetd.d
目录下有一个对应的配置文件,xinetd将在启动时或被要求时读取这些文件。
1.2 安装及启动
默认情况下ubuntu没有安装xinetd服务。apt install xinetd
安装后,服务默认是disable,我们要修改需要启动服务的属性,然后重启xinetd。
#启动
service xinetd start
#停止
service xinetd stop
#重启
service xinetd restart
1.3 使用xinetd的服务
原则上任何系统服务都可以使用xinetd,然而最适合的应该是那些常用的网络服务,并且这个服务的请求数目和频繁程度不会太高。像DNS和Apache就不适合采用这种方式,而像FTP、Telnet、SSH等就适合使用xinetd模式。
系统默认使用xinetd的服务可以分为如下几类:
① 标准Internet服务:telnet、ftp。
② 信息服务:finger、netstat、systat。
③ 邮件服务:imap、imaps、pop2、pop3、pops。
④ RPC服务:rquotad、rstatd、rusersd、sprayd、walld。
⑤ BSD服务:comsat、exec、login、ntalk、shell、talk。
⑥ 内部服务:chargen、daytime、echo、servers、services、time。
⑦ 安全服务:irc。
⑧ 其他服务:name、tftp、uucp。
1.3 /etc/services文件
该文件中记录网络服务名和它们对应使用的端口号及协议。文件中的每一行对应一种服务,它由4个字段组成,中间用Tab键或空格键分隔,分别表示 “服务名称”、“使用端口”、“协议名称”及“别名”。在一般情况下,不要修改该文件的内容,因为这些设置都是Internet标准的设置,很多的系统程序要使用这个文件。Linux系统的端口号的范围为0~65535,不同范围的端口号有不同的意义
- 0:不使用。
- 1~1023:系统保留,只能由root用户使用。
- 1024~4999:由客户端程序自由分配。
- 5000~65535:由服务器程序自由分配。
/etc/services
文件保存了服务和端口的对应关系。但是通常服务的配置文件里会自行定义端口。那么两者间是什么关系呢?事实上,服务最终采用的方案仍然是自己的端口定义配置文件。
- 如何使应用程序不再关心服务所使用的端口号?
1)确定服务程序名称,协议,端口号
2)在/etc/services
中配置1)中信息
3)应用程序可以不直接使用端口号,通过函数getservbyname("server","tcp")
获取端口号。
4)如果服务想更改端口号只要更改/etc/services
中的端口号就可以了,应用程序不需要做任何更改。
注:同时可以通过函数getservbyport(htons(50),“tcp”)
获取对应端口和协议上的服务名。
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
char buff[128];
char* host;
if(argc == 1)
host = "localhost";
else
host = argv[1];
struct hostent* hostinfo = gethostbyname(host);
if(!hostinfo){
fprintf(stderr,"no host: %s\n",host);
exit(1);
}
struct servent* servinfo = getservbyname("daytime","tcp");
if(!servinfo){
fprintf(stderr,"no daytime service\n");
exit(1);
}
printf("daytime port is %d\n",ntohs(servinfo->s_port));
//客户程序连接到本机的服务器daytime
struct sockaddr_in address;
int sockfd = socket(AF_INET,SOCK_STREAM,0);
address.sin_family = AF_INET;
address.sin_port = servinfo->s_port;
address.sin_addr = *(struct in_addr*)(*hostinfo->h_addr_list);
int len = sizeof(address);
int result = connect(sockfd,(struct sockaddr*)&address,len);
if(result == -1){
perror("oops: getdate");
exit(1);
}
int result = read(socket,buff,sizeof(buff));
buff[result] = '\0';
printf("read %d byte: %s",result,buff);
close(sockfd);
exit(0);
}