设为首页 收藏本站
查看: 1548|回复: 0

[经验分享] UNP卷1:第十一章(名字与地址转换)

[复制链接]

尚未签到

发表于 2015-11-24 02:57:31 | 显示全部楼层 |阅读模式
1. gethostbyname函数
  

#include <netdb.h>
struct hostent *gethostbyname( const char *hostname );
返回:若成功则为非空指针,若出错则为NULL且设置h_errno而hostent的结构如下:  
  

struct hostent{
char    *h_name;
char    *h_aliases;
int        h_addrtype;
int        h_length;
char    **h_addr_list;
};书上的例子如下:(实际上在ubuntu系统上,gethostbyname&#20284;乎会出错)  
  

#include &quot;myunp.h&quot;
int main( int argc, char **argv )
{
char*ptr, **pptr;
charstr[ INET_ADDRSTRLEN ];
structhostent*hptr;
while ( --argc > 0 ){
ptr = *++argv;
if ( ( hptr = gethostbyname( ptr ) ) == NULL ){
printf(&quot;gethostbyname error for host:%s:%s\n&quot;, ptr, hstrerror( h_errno ) );
continue;
}
printf(&quot;official hostname:%s\n&quot;, hptr->h_name );
for ( pptr = hptr->h_aliases; *pptr != NULL; pptr++ )
printf(&quot;\talias:%s\n&quot;, *pptr );
switch( hptr->h_addrtype ){
case AF_INET:
pptr = hptr->h_addr_list;
for ( ; *pptr != NULL; pptr++ )
printf(&quot;\taddress name:%s\n&quot;, *pptr );
//printf(&quot;\taddress:%s\n&quot;, inet_ntop( hptr->h_addrtype, *pptr, str, sizeof(str)));
break;
default:
printf(&quot;unknown address type&quot;);
break;
}
}
exit(0);
}

程序输出:  
  

root@ThinkPad-T430i:/home/leichaojian# cc hostent.c -o hostent
root@ThinkPad-T430i:/home/leichaojian# ./hostent www.baidu.com
official hostname:www.a.shifen.com
alias:www.baidu.com
address name:�a!kwww.�a!lifen.com
address name:�a!lifen.com

  所以执行inet_ntop时候程序直接报异常。
  



2. 测试inet_ntop和inet_pton函数
  

#include &quot;myunp.h&quot;
2
3 int main( void )
4 {
5     char *ptr = &quot;127.0.0.1&quot;;
6     char str[ 1024 ];
7     struct sockaddr_in  servaddr;
8
9     bzero( &servaddr, sizeof( servaddr ) );
10     servaddr.sin_family = AF_INET;
11     servaddr.sin_port = htons( SERV_PORT );
12     inet_pton( AF_INET, ptr, &servaddr.sin_addr);
13
14     inet_ntop( AF_INET, ( SA * )&servaddr.sin_addr, str, sizeof( str ) );
15
16     printf(&quot;%s\n&quot;, str );
17     return 0;
18 }
程序输出:  
  

leichaojian@ThinkPad-T430i:~$ ./test
127.0.0.1

3. getservbyname和getservbyport函数
  一个根据给定名字查找相应服务,一个给定端口号和可选协议查找相应服务。
  

#include <stdio.h>
#include <netdb.h>
int main( int argc, char **argv )
{
struct servent*sptr;
sptr = getservbyname( &quot;domain&quot;, &quot;udp&quot; );
sptr = getservbyname( &quot;ftp&quot;, &quot;tcp&quot; );
sptr = getservbyname( &quot;ftp&quot;, &quot;NULL&quot; );
sptr = getservbyname( &quot;ftp&quot;, &quot;udp&quot; );
sptr = getservbyport( htons( 53 ), &quot;udp&quot; );
sptr = getservbyport( htons( 21 ), &quot;tcp&quot; );
sptr = getservbyport( htons( 21 ), &quot;NULL&quot; );
sptr = getservbyport( htons( 21 ), &quot;udp&quot; );
return 0;
}


  
  程序输出:
  

(gdb) break 8
Breakpoint 1 at 0x4005dc: file getservbynameport.c, line 8.
(gdb) r
Starting program: /home/leichaojian/getservbynameport
Breakpoint 1, main (argc=1, argv=0x7fffffffde58) at getservbynameport.c:8
8sptr = getservbyname( &quot;domain&quot;, &quot;udp&quot; );
(gdb) n
9sptr = getservbyname( &quot;ftp&quot;, &quot;tcp&quot; );
(gdb) p *sptr
$1 = {s_name = 0x602010 &quot;domain&quot;, s_aliases = 0x602020, s_port = 13568, s_proto = 0x60201b &quot;udp&quot;}
(gdb) n
10sptr = getservbyname( &quot;ftp&quot;, &quot;NULL&quot; );
(gdb) p *sptr
$2 = {s_name = 0x602010 &quot;ftp&quot;, s_aliases = 0x602020, s_port = 5376, s_proto = 0x602018 &quot;tcp&quot;}
(gdb) n
11sptr = getservbyname( &quot;ftp&quot;, &quot;udp&quot; );
(gdb) p *sptr
Cannot access memory at address 0x0
(gdb) n
13sptr = getservbyport( htons( 53 ), &quot;udp&quot; );
(gdb) p *sptr
Cannot access memory at address 0x0
(gdb) n
14sptr = getservbyport( htons( 21 ), &quot;tcp&quot; );
(gdb) p *sptr
$3 = {s_name = 0x603290 &quot;domain&quot;, s_aliases = 0x6032a0, s_port = 13568, s_proto = 0x60329b &quot;udp&quot;}
(gdb) n
15sptr = getservbyport( htons( 21 ), &quot;NULL&quot; );
(gdb) p *sptr
$4 = {s_name = 0x603290 &quot;ftp&quot;, s_aliases = 0x6032a0, s_port = 5376, s_proto = 0x603298 &quot;tcp&quot;}
(gdb) n
16sptr = getservbyport( htons( 21 ), &quot;udp&quot; );
(gdb) p *sptr
Cannot access memory at address 0x0
(gdb) n
18return 0;

  

4. getaddrinfo函数
  此函数可用来代替gethostbyname和gethostbyaddr。
  

#include <netdb.h>
int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );
返回:若成功则为0,若出错则为非0参数1为主机名或地址串(点分十进制数串),service参数是一个服务名或十进制端口号数串,hints目前就直接置为NULL,而result则是我们需要的信息:  
  

struct addrinfo{
intai_flags;
intai_family;
intai_socktype;
intai_addrlen;
socklen_tai_addrlen;
char*ai_canonname;
struct sockaddr *ai_addr;
struct addrinfo *ai_next;
};

测试用例如下:  
  

#include <stdio.h>
#include <netdb.h>
int main( int argc, char **argv )
{
struct addrinfo hints, *res;
struct sockaddr_in*addr;
charstr[ 1024 ];
getaddrinfo( &quot;ThinkPad-T430i&quot;, &quot;domain&quot;, NULL, &res );
for ( ;res->ai_next;res = res->ai_next ){
printf(&quot;ai_falgs:%d\n&quot;, res->ai_flags);
printf(&quot;ai_family:%d\n&quot;, res->ai_family);
printf(&quot;ai_socktype:%d\n&quot;, res->ai_socktype);
printf(&quot;ai_addrlen:%d\n&quot;, res->ai_addrlen);
printf(&quot;ai_canonname:%s\n&quot;, res->ai_canonname);
addr = ( struct sockaddr_in * )res->ai_addr;
printf(&quot;sin_family:%d\n&quot;, addr->sin_family);
printf(&quot;sin_port:%d\n&quot;, ntohs( addr->sin_port ) );
inet_ntop( addr->sin_family, &addr->sin_addr, str, sizeof( str ) );
printf(&quot;sin_addr:%s\n&quot;, str);
}
return 0;
}程序输出:  
  

leichaojian@ThinkPad-T430i:~$ cc getaddrinfo.c
leichaojian@ThinkPad-T430i:~$ ./a.out
ai_falgs:40
ai_family:2
ai_socktype:1
ai_addrlen:16
ai_canonname:(null)
sin_family:2
sin_port:53
sin_addr:127.0.1.1

  

5. 使用getaddrinfo来完成TCP时间获取服务器程序

1)时间获取客户程序
  

#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#define MAXLINE 1024
int tcp_connect( const char *host, const char *serv );
int main( int argc, char **argv )
{
intsockfd, n;
charrecvline[ MAXLINE + 1 ];
socklen_tlen;
struct sockaddr_incliaddr;
if ( argc != 3 ){
printf(&quot;argument should be 3\n&quot;);
exit(1);
}
sockfd = tcp_connect( argv[1], argv[2]);
len = sizeof( cliaddr );
getpeername( sockfd, ( struct sockaddr * )&cliaddr, len );
inet_ntop( AF_INET, &cliaddr.sin_addr, recvline, sizeof( recvline ) );
printf(&quot;connect to %s\n&quot;, recvline);
while ( ( n = read( sockfd, recvline, MAXLINE )) > 0 ){
recvline[ n ] = 0;
fputs( recvline, stdout );
}
exit( 0 );
}
int tcp_connect( const char *host, const char *serv )
{
intsockfd, n;
structaddrinfo hints, *res, *ressave;
structsockaddr_in*cliaddr;
bzero( &hints, sizeof( struct addrinfo ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ( ( n = getaddrinfo( host, serv, &hints, &res ) ) != 0 ){
printf(&quot;tcp_connect error for %s,%s:%s&quot;, host, serv, gai_strerror(n));
exit(1);
}
ressave = res;
do{
sockfd = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
if ( sockfd < 0 )
continue;
if ( connect( sockfd, res->ai_addr, res->ai_addrlen ) == 0 )
break;
//用于调试
cliaddr = ( struct sockaddr_in * )res->ai_addr;
close( sockfd );
} while ( ( res = res->ai_next ) != NULL );
if ( res == NULL )
printf(&quot;tcp_connect error for %s,%s\n&quot;, host, serv );
freeaddrinfo( ressave );
return ( sockfd );
}

程序输出:  
  

leichaojian@ThinkPad-T430i:~$ ./newdaytimetcpcli ThinkPad-T430i daytime
connect to 0.0.0.0
30 SEP 2014 00:21:58 CST
备注:这里要开启时间,具体操作如下  
  1) 安装
  

leichaojian@ThinkPad-T430i:~$ sudo apt-get install xinetd
2) 修改配置如下:  
  

leichaojian@ThinkPad-T430i:~$ cd /etc/xinetd.d
leichaojian@ThinkPad-T430i:/etc/xinetd.d$ vim daytime
3) 具体修改:  
  将disable=yes改为disable=no(两处均要修改)
  4)我不知道如何重新载入,所以直接重启了电脑。


  



2)时间获取服务器程序
  #include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <time.h>
#define MAXLINE 1024
int tcp_listen( const char *host, const char *serv, socklen_t *addrlenp );
int main( int argc, char **argv )
{
intlistenfd, connfd;
socklen_tlen;
charbuff[ MAXLINE ];
time_tticks;
structsockaddr_incliaddr;
listenfd = tcp_listen( argv[ 1 ], argv[ 2 ], NULL );
for ( ; ; ){
len = sizeof( cliaddr );
connfd = accept( listenfd, ( struct sockaddr *)&cliaddr, &len );
inet_ntop( AF_INET, &cliaddr.sin_addr, buff, sizeof( buff ) );
printf(&quot;conneciton from %s\n&quot;, buff );
ticks = time( NULL );
snprintf( buff, sizeof( buff ), &quot;%.24s\r\n&quot;, ctime(&ticks));
write( connfd, buff, strlen(buff));
close( connfd );
}
}
int tcp_listen( const char *host, const char *serv, socklen_t *addrlenp )
{
intlistenfd, n;
constint on = 1;
structaddrinfo hints, *res, *ressave;
bzero( &hints, sizeof( struct addrinfo ) );
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ( ( n = getaddrinfo( host, serv, &hints, &res ) ) != 0 ){
printf(&quot;tcp_listen error for %s,%s: %s\n&quot;, host, serv, gai_strerror(n));
}
ressave = res;
do{
listenfd = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
if ( listenfd < 0 )
continue;
setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if ( bind( listenfd, res->ai_addr, res->ai_addrlen) == 0 )
break;
close( listenfd );
} while(( res = res->ai_next) != NULL );
if ( res == NULL ){
printf(&quot;tcp_listen error for %s,%s&quot;, host, serv);
}
listen( listenfd, 5 );
if ( addrlenp )
*addrlenp = res->ai_addrlen;
freeaddrinfo(ressave);
return (listenfd );
}

服务端运行:
  leichaojian@ThinkPad-T430i:~$ ./newdaytimetcpserv ThinkPad-T430i 9877
conneciton from 127.0.0.1
客户端运行:
  leichaojian@ThinkPad-T430i:~$ ./newdaytimetcpcli ThinkPad-T430i 9877
connect to 0.0.0.0
Tue Sep 30 18:14:25 2014




6. 使用getaddrinfo来完成UDP时间获取服务器程序
  

1)时间获取客户端程序
  #include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#define MAXLINE 1024
int udp_client(const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp );
int main(int argc, char **argv)
{
intsockfd, n;
charrecvline[ MAXLINE + 1 ];
socklen_tsalen;
structsockaddr *sa;
if (argc != 3){
printf(&quot;argument should be 3\n&quot;);
exit(1);
}
sockfd = udp_client(argv[1], argv[2], (void **)&sa, &salen);
sendto(sockfd, &quot;&quot;, 1, 0, sa, salen);
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
recvline[n] = '\0';
fputs(recvline, stdout);
exit(0);
}
int udp_client(const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp )
{
intsockfd, n;
structaddrinfo hints, *res, *ressave;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0){
printf(&quot;udp_client error for %s,%s:%s\n&quot;, host, serv, gai_strerror(n));
exit(1);
}
ressave = res;
do{
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd >= 0)
break;
}while ((res = res->ai_next) != NULL);
if (res == NULL){
printf(&quot;udp_client error for %s,%s\n&quot;, host, serv);
exit(1);
}
*saptr = malloc(res->ai_addrlen);
memcpy(*saptr, res->ai_addr, res->ai_addrlen);
*lenp = res->ai_addrlen;
freeaddrinfo(ressave);
return (sockfd);
}

程序输出:
  leichaojian@ThinkPad-T430i:~$ ./newdaytimeudpcli ThinkPad-T430i daytime
30 SEP 2014 18:37:24 CST




2) 时间获取服务端程序
  #include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <time.h>
#define MAXLINE 1024
int udp_server(const char *host, const char *serv, socklen_t *addrlenp);
int main(int argc, char **argv)
{
intsockfd;
ssize_tn;
charbuff[MAXLINE];
time_tticks;
socklen_tlen;
structsockaddr_incliaddr;
sockfd = udp_server( argv[1], argv[2], NULL);
for ( ; ; ){
len = sizeof(cliaddr);
n = recvfrom(sockfd, buff, MAXLINE, 0, (struct sockaddr *)&cliaddr, &len);
inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff));
printf(&quot;datagram from %s\n&quot;, buff );
ticks = time(NULL);
snprintf(buff, sizeof(buff), &quot;%.24s\r\n&quot;, ctime(&ticks));
sendto(sockfd, buff, strlen(buff), 0, (struct sockaddr *)&cliaddr, len);
}
}
int udp_server(const char *host, const char *serv, socklen_t *addrlenp)
{
intsockfd, n;
structaddrinfo hints, *res, *ressave;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0){
printf(&quot;udp_server error for %s,%s:%s&quot;, host, serv, gai_strerror(n));
exit(1);
}
ressave = res;
do{
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0)
continue;
if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break;
close(sockfd);
}while ((res = res->ai_next) != NULL);
if (res == NULL){
printf(&quot;udp_server error for %s,%s\n&quot;, host, serv);
exit(1);
}
if (addrlenp)
*addrlenp = res->ai_addrlen;
freeaddrinfo(ressave);
return (sockfd);
}

服务器运行:
  leichaojian@ThinkPad-T430i:~$ ./newdaytimeudpserv ThinkPad-T430i 9877
datagram from 127.0.0.1
客户端运行:
  leichaojian@ThinkPad-T430i:~$ ./newdaytimeudpcli ThinkPad-T430i 9877
Tue Sep 30 18:56:41 2014



  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-142788-1-1.html 上篇帖子: nagios与cacti、ntop整合 下篇帖子: CF E. Vanya and Brackets(添加一对括号使得表达式的值最大)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表