网络信息相关函数
gethostbyname和gethostbyaddr
gethostbyname根據(jù)主機名稱獲取主機的完整信息,gethostbyaddr根據(jù)IP地址獲取主機的完整信息。
gethostname通常先在本地/etc/hosts配置文件查找,如果沒有再向DNS服務(wù)器查找。
#include <unistd.h> #include <sys/socket.h>int gethostname(char *name, size_t len);struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); struct hostent {char *h_name; /* 主機名 */char **h_aliases; /* 主機別名列表 */int h_addrtype; /* 地址類型 */int h_length; /* 地址長度 */char **h_addr_list; /* ip地址列表 */ }name參數(shù)指定目標(biāo)主機名,addr參數(shù)指定目標(biāo)主機的IP地址,len參數(shù)指定addr的地址大小,type參數(shù)指定addr所指IP地址的類型。
代碼實現(xiàn):根據(jù)主機名baidu和百度的ip地址獲取百度的信息。
getservbyname和getservbyport
#include <netdb.h>struct servent *getservent(void); struct servent *getservbyname(const char *name, const char *proto); struct servent *getservbyport(int port, const char *proto);getservbyname函數(shù)根據(jù)名稱獲取某個服務(wù)的完整信息。
getservbyport函數(shù)根據(jù)端口號獲取某個服務(wù)的完整信息。
name參數(shù)指定服務(wù)名字。
port參數(shù)指定目標(biāo)服務(wù)對應(yīng)的端口號。
proto參數(shù)指定服務(wù)類型。
函數(shù)返回的都是servent指針,結(jié)構(gòu)體servent定義如下:
struct servent {char *s_name; /* 服務(wù)名稱 */char **s_aliases; /* 服務(wù)別名列表 */int s_port; /* 端口號 */char *s_proto; /* 服務(wù)類型 */ }代碼:編寫一個程序,使用主機名和服務(wù)名訪問目標(biāo)服務(wù)器上的daytime服務(wù),獲取該機器的系統(tǒng)時間。
#include <iostream> #include <netdb.h> #include <unistd.h> #include <assert.h> #include <cstring> using namespace std;int main(int argc, char* argv[]) {/* 主函數(shù)需要1個參數(shù) */assert(argc == 2);char* host = argv[1];/* 獲取目標(biāo)主機的地址信息 */hostent* hostinfo = gethostbyname(host);assert(hostinfo);/* 獲取daytime服務(wù)信息 */servent* servinfo = getservbyname("daytime", "tcp");assert(servinfo);printf("daytime port is %d\n", servinfo->s_port);/* 創(chuàng)建socket地址 */sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = servinfo->s_port;addr.sin_addr = *(in_addr*)*hostinfo->h_addr_list;/* 創(chuàng)建socket文件描述符 */int sockfd = socket(AF_INET, SOCK_STREAM, 0);assert(sockfd >= 0);/* 連接 */int ret = connect(sockfd, (sockaddr*)&addr, sizeof addr);assert(ret != -1);/* 數(shù)據(jù)讀寫 */char buffer[128];memset(buffer, '\0', sizeof buffer);ret = read(sockfd, buffer, sizeof buffer);assert(ret > 0);printf("the day is: %s\n", buffer);/* 關(guān)閉socket */close(sockfd);return 0; }注意上面四個函數(shù)是不可重入的,非線程安全,netdb.h給出了可重入版本,在原函數(shù)尾部加上_r即可。
./a.out localhost daytime port is 3328 a.out: GetSysTime.cpp:35: int main(int, char**): Assertion `ret != -1' failed. [1] 30605 abort (core dumped) ./a.out localhost失敗在連接這一步,這是因為默認(rèn)xinetd是關(guān)閉daytime的修改配置文件
service daytime {disable = notype = INTERNALid = daytime-streamsocket_type = streamprotocol = tcpuser = rootwait = no }# This is the udp version. service daytime {disable = notype = INTERNALid = daytime-dgramsocket_type = dgramprotocol = udpuser = rootwait = yes }將disable = yes 改成disable = no,上圖所示,并重啟xinetd。
sudo systemctl restart xinetd.service查看是否服務(wù)已經(jīng)啟動
sudo systemctl status xinetd.service ● xinetd.service - LSB: Starts or stops the xinetd daemon.Loaded: loaded (/etc/init.d/xinetd; generated)Active: active (running) since Mon 2021-10-04 02:59:02 PDT; 17s agoDocs: man:systemd-sysv-generator(8)Process: 30709 ExecStart=/etc/init.d/xinetd start (code=exited, status=0/SUCCESS)Tasks: 1 (limit: 2273)Memory: 364.0KCGroup: /system.slice/xinetd.service└─30734 /usr/sbin/xinetd -pidfile /run/xinetd.pid -stayalive -inetd_compat>開啟服務(wù)后,再次嘗試:
./a.out localhost daytime port is 3328 the day is: 04 OCT 2021 03:01:07 PDT雖然中間遇到一些小問題,最終還是解決了。
getaddrinfo
#include <netdb.h>int getaddrinfo(const char *node, const char *service,const struct addrinfo *hints,struct addrinfo **res);此函數(shù)既能通過主機名獲得IP地址,也能通過服務(wù)名獲取端口號。此函數(shù)是否可重用取決于內(nèi)部調(diào)用的是gethostbyname和getservbyname函數(shù)的可重入版本。
hostname可以接收主機名,也可以表示接收字符串表示的IP地址。
service可以接收服務(wù)名,也可以接收端口號。
hints參數(shù)三十應(yīng)用程序給addrinfo的一個提示,以對getaddrinfo的輸出進(jìn)行更加精準(zhǔn)的控制。
使用hints參數(shù)的時候,可以設(shè)置ai_flags,ai_family,ai_socktype,ai_protocol四個字段,其它字段必須設(shè)置為NULL。
getaddrinfo隱士分配內(nèi)存。調(diào)用結(jié)束后使用下面函數(shù)釋放內(nèi)存
#include <netdb.h>void freeaddrinfo(struct addrinfo* res);getnameinfo
總結(jié)
- 上一篇: GMM-HMM语音识别
- 下一篇: TK域名转向