UNP编程:31---名字与地址转换之(服务解析函数:getservbyname()、getservbyport()、struct servent)
一、服务与地址的关系
- 一个端口代表一个服务(服务进程),因此可以使用服务名来代替端口的使用
- 像主机一样,服务也通常靠名字来认知
- 如果我们在程序代码中通过其名字而不是其端口号来指代一个服务,而且从名字到端口号的映射关系保存在一个文件中(通常是/etc/services),那么即使端口号发生变动,我们需修改的仅仅是/etc/services文件中的某 一行,而不必重新编译应用程序。getservbyname函数用于根据给定名字查找相应服务
- 赋予各个服务的端口号规范列表由IANA通过http://www.iana.org/assignments/port-num-bers维护。/etc/services文件通常包含由IANA维护的规范赋值列表的某个子集
二、struct servent结构体
struct servent {char *s_name; /* official service name */char **s_aliases; /* alias list */int s_port; /* port number */char *s_proto; /* protocol to use */
}
参数
- s_name:服务的官方名称
- s_aliases:服务别名列表
- s_port:服务对应的端口号
- s_proto:与此服务一起使用的协议的名称
三、getservbyname
#include <netdb.h>
struct servent *getservbyname(const char *servname, const char *protoname);
- 功能:通过服务名与服务的协议类型返回一个struct servent结构体信息
参数
- 参数1:服务的名称
- 参数2:服务对应的协议类型
返回值
- 成功:返回struct servent结构体指针
- 失败:返回NULL
参数使用的注意事项
- 参数1必须指定,参数2可以选择忽略或指定
- 如果protoname指定:如果同时指定了协议(即protoname参数为非空指针),那么指定服务必须有匹配的协议。有些因特网服务既用TCP也用UDP提供(例如DNS),其他因特网服务则仅仅支持单个协议(例如FTP要求使用TCP,而不能使用UDP)
- 如果protoname未指定:如果protoname未指定而servname指定服务支持多个协议,那么返回哪个端口号取决于实现。通常情况下这种选择无关紧要,因为支持多个协议的服务往往使用相同的TCP端口号和UDP端口号,不过这点 并没有保证
- 例如:既然FTP仅仅支持TCP,第二个调用和第三个调用等效,第四个调用则会失败
struct servent *sptr;sptr = getservbyname("domain", "udp"); /* DNS using UDP */ sptr = getservbyname("ftp", "tcp"); /* FTP using TCP */ sptr = getservbyname("ftp", NULL); /* FTP using TCP */ sptr = getservbyname("ftp", "udp"); /* this call will fail */
演示案例
//程序传入主机名和服务名,先根据主机名得到IP //然后根据服务名获得端口。然后创建一个套接字连接这个IP和端口对应的服务 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/socket.h> #include<netinet/in.h> #include<sys/types.h> #include<arpa/inet.h> #include<string.h> #include<netdb.h> #define MAXLINE 1024int Socket(int domain,int type,int protocal);int main(int argc, char **argv) {int sockfd, n;char recvline[MAXLINE + 1];struct sockaddr_in servaddr;struct in_addr **pptr;struct in_addr *inetaddrp[2];struct in_addr inetaddr;struct hostent *hp; //保存主机信息struct servent *sp; //保存服务信息if (argc != 3){perror("usage: daytimetcpcli1 <hostname> <service>");exit(1);}//通过域名解析获得主机的信息if ( (hp = gethostbyname(argv[1])) == NULL)//如果没有解析到{if (inet_aton(argv[1], &inetaddr) == 0) {//将字符串IP转为网络IPprintf("hostname error for %s: %s\n", argv[1], hstrerror(h_errno));exit(2);} else {//转换的网络IP存放在inetaddrp[0]中inetaddrp[0] = &inetaddr;inetaddrp[1] = NULL;pptr = inetaddrp;}} //将解析到的IP地址列表给pptrelse {pptr = (struct in_addr **) hp->h_addr_list;}//解析服务信息if ((sp = getservbyname(argv[2], "tcp")) == NULL){printf("getservbyname error for %s\n", argv[2]);exit(3);}//尝试连接这个服务for ( ; *pptr != NULL; pptr++){sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = sp->s_port;memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));printf("trying %s\n",inet_ntoa((struct in_addr)servaddr.sin_addr));//连接服务if (connect(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) == 0)break; //连接成功就breakperror("connect error");close(sockfd);}if (*pptr == NULL){perror("unable to connect");exit(5);}while ((n = read(sockfd, recvline, MAXLINE)) > 0) {recvline[n] = 0;fputs(recvline, stdout);}exit(0); }int Socket(int domain,int type,int protocal) {int sockFd=socket(domain,type,protocal);if(sockFd<0){perror("socket");exit(4);}return sockFd; }
四、getservbyport
#include <netdb.h>
struct servent *getservbyport(int port, const char *proto);//返回值:成功返回struct servent结构体指针;失败返回NULL
- 功能:通过端口号与端口对应的服务协议类型返回一个struct servent结构体信息
注意
- 注意事项一:参数1必须为网络字节序的端口号
struct servent *sptr;sptr = getservbyport(htons(53),"udp"); /* DNS using UDP */ sptr = getservbyport(htons(21), "tcp"); /* FTP using TCP */ sptr = getservbyport(htons(21), NULL); /* FTP using TCP */ sptr = getservbyport(htons(21), "udp"); /* this call will fail */
- 注意事项二:一个端口可能有多种协议类型,因此参数2对应于不同的协议类型,返回的信息也不同
- 必须清楚的是,有些端口号在TCP上用于一种服务,在UDP上却用于完全不同的另一种服 务。例如:表明端口514在TCP上由rsh命令使用,在UDP上却由syslog守护进程使用。512~514范围内的端口都有这个特性
UNP编程:31---名字与地址转换之(服务解析函数:getservbyname()、getservbyport()、struct servent)相关推荐
- 网络编程学习——名字与地址转换(一)
2019独角兽企业重金招聘Python工程师标准>>> 1 域名系统 域名系统(Domain Name System,DNS)主要用于主机名字与IP地址之间的映射.主机名既可以是一个 ...
- UNP总结 Chapter 11 名字与地址转换
本章讲述在名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IP地址间进行转换,getservbyname和getservbyport在服务器名字和端口 ...
- Unix网络编程学习笔记之第11章 名字与地址转换
一. 域名系统(DNS) 1. 简介 DNS主要用于主机名和IP地址之间的映射. 主机名可以是简单的名字ljm,也可以是全限定域名ljm.localdomainbaidu.com等. 2.资源记录 D ...
- 《UNIX网络编程:套接字联网API》啃书笔记(第8UDP套接字编程、11章地址转换)
基本UDP套接字编程 下图为UDP客户/服务器程序的函数调用: 注意客户不与服务器建立连接,而是只管使用sendto函数给服务器发送数据报,其中必须指定目的地的地址作为参数.类似的,服务器不接受来自客 ...
- 名字与地址转换getservbyname 与 getservbyport函数
名字与地址转换getservbyname 与 getservbyport函数 服务也通常靠名字来标志,getservbyname函数用于根据给定名字查找相应服务. #include struct ...
- UNP Chapter 9 - 基本名字与地址转换
9.1. 概述 本章讲述在名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IP地址间进行转换,getservbyname和getservbyport在 ...
- 二进制转换为十进制c语言编程,将二进制IP地址转换成十进制(C语言程序实现)
将二进制IP地址转换成十进制(C语言程序实现) /* * Name: IP Address * Funcion: To convert binary numbers to decimal number ...
- UNP Chapter 11 - 高级名字与地址转换
11.1. 概述 函数gethostbyname和gethostbyaddr是依赖于协议的,使用前一个函数时,我们必须知道放置结果的套接口地址结构的成员是哪一种(举例来说,IPv4使用sin_addr ...
- UNP编程:29---名字与地址转换之(域名系统)
一.域名系统的概念 域名系统(Domain Name System,DNS)主要用于主机名字与IP地址之间的映射. 主机名既可以是一个简单名字(simple name),例如solaris或bsdi, ...
- (域名、主机名、服务名、端口号)名字与地址的转换 (gethostbyname、getservbyname、getaddrinfo、getnameinfo等)
转载地址 本章讲述在名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IP地址间进行转换,getservbyname和getservbyport在服务器 ...
最新文章
- ArXiv 2020 | 抖音“变身漫画”滤镜背后的技术,难道来自这篇论文?
- sql server无效的对象名称 - 但表列在SSMS表列表中
- 【转】linux tar 压缩
- 后年将有60亿部手机!
- Hive的两种操作模式
- nhibernate:composite-id class must override Equals()
- FLV封装格式介绍及解析
- 计算机的科学原理是什么,人工智能的工作原理是什么?
- 展望Java的未来:空值类型
- 字节流转化为文件流_C#文件转换为字节流及字节流转换为文件
- 6大设计原则之接口隔离原则
- 前锋php人工智能_人工智能除了学习php,还应该学什么?
- arduino蜂鸣器音乐代码青花瓷_教你用 Arduino 制造简易金属探测器
- [汇编学习笔记][第十六章直接定址表]
- php利用svn hooks将程序自动发布到测试环境
- laravel框架使用phpQuery库来实现网页抓取
- java wps linux 安装_安装wps for linux无法启动
- 详解Guitar Pro 7小节的组织定义
- directdraw(directdraw怎么开启)
- php识别word语言,PHP读取word文档