UNP编程:31---名字与地址转换之(服务解析函数:getservbyname()、getservbyport()、struct servent)
生活随笔
收集整理的這篇文章主要介紹了
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,第二個調用和第三個調用等效,第四個調用則會失敗
演示案例
//程序傳入主機名和服務名,先根據主機名得到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必須為網絡字節序的端口號
- 注意事項二:一個端口可能有多種協議類型,因此參數2對應于不同的協議類型,返回的信息也不同
- 必須清楚的是,有些端口號在TCP上用于一種服務,在UDP上卻用于完全不同的另一種服 務。例如:表明端口514在TCP上由rsh命令使用,在UDP上卻由syslog守護進程使用。512~514范圍內的端口都有這個特性
總結
以上是生活随笔為你收集整理的UNP编程:31---名字与地址转换之(服务解析函数:getservbyname()、getservbyport()、struct servent)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【华为 OJ 】等差数列
- 下一篇: 电传输之POE供电的介绍