Services are represented by the port number portion of the address. Each service is offered on a unique, well-known port number. We can map a service name to a port number withgetservbyname, map a port number to a service name withgetservbyport, or scan the services database sequentially withgetservent.(APUE-2e)
地址的端口部分和服务是一一对应的,getservbyname()和 getservbyport()能将二者相互映射(map)。
/* Description of data base entry for a single service. */
struct servent
{
char *s_name; /* Official service name. */
char **s_aliases; /* Alias list. */
int s_port; /* Port number. */
char *s_proto; /* Protocol to use. */
};
struct servent *getservent(void);
struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
void setservent(int stayopen);
void endservent(void);
说明:
(1) 这几个函数的原理是查询 /etc/services 文件(ubuntu下)
(2) s_port is in network byte order, you should usentohs()(not htohl(), I don't know why) to convert it to host byte order.
/**
* getservent()
* OS: Ubuntu 11.04 Server
*/
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
static void printserv(struct servent *serv);
int main()
{
struct servent *serv = NULL;
setservent(1);
while( (serv = getservent()) != NULL )
{
printserv(serv);
printf("\n");
}
endservent();
return 0;
}
static void printserv(struct servent *serv)
{
char **p = NULL;
printf("service name: %s\n", serv->s_name);
for(p = serv->s_aliases; *p != NULL; p++)
{
printf("aliase: %s\n", *p);
}
printf("port number: %d\n", ntohs(serv->s_port)); // Note: the port here is in network byte order.
//printf("port number: %x\n", serv->s_port);
//printf("port number: %d\n", ntohl(serv->s_port)); // Note: use ntohs(), not ntohl(), I don't know why.
printf("protocol: %s\n", serv->s_proto);
}
/*
output:
service name: tcpmux
port number: 256
protocol: tcp
service name: echo
port number: 1792
protocol: tcp
service name: echo
port number: 1792
protocol: udp
...
/etc/services:
tcpmux 1/tcp # TCP port service multiplexer
echo 7/tcp
echo 7/udp
...
*/