日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UNP编程:31---名字与地址转换之(服务解析函数:getservbyname()、getservbyport()、struct  servent)

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。