Internet Application 5:绝情的指针

TASK 1: Find the fore-mentioned header files in your system

使用locate或者find命令,输出结果略…

TASK 2: Find the host byte order of your machine

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>

int main(){
union{
short s;
char c[sizeof(short)];
}un;

un.s = 0x0102;

if(sizeof(short) == 2){
if(un.c[0]==1&&un.c[1]==2)
printf("big-endian\n");
else if(un.c[0]==2&&un.c[1]==1)
printf("little-endian\n");
else
printf("unknown\n");
}else
printf("sizeof(short) = %d\n", sizeof(short));
exit(0);
}

运行结果:

1
2
3
[email protected]:~/lab5$ gcc HostOrder.c -o HostOrder
[email protected]:~/lab5$ ./HostOrder
little-endian

TASK 3: Use “man” to learn the usage of

  • netstat, ifconfig, ping, traceroute
1
2
3
4
netstat     -  Print  network connections, routing tables, interface statistics, masquerade connections, and multicast memberships
ifconfig - configure a network interface
ping, ping6 - send ICMP ECHO_REQUEST to network hosts
traceroute - print the route packets trace to network host

TASK 4: Write a program to find the host information of a given host

The host is specified in domain name: ./<exefile> www.baidu.com
Your program shall list the official name, all the aliases, the address type, the address length, all the IP address in numbers-and-dots format.

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
struct hostent *hostinfo;
struct in_addr *ip;

if (argc != 2) {
printf("Usage:\n%s hanxueying.com\n", argv[0]);
exit(1);
}

//lookup host infomation by domain name.
hostinfo = gethostbyname(argv[1]);

//print hostinfo->h_name here.
printf("The official name is: %s \n",hostinfo->h_name);

//print hostinfo->h_aliases here.
char **addr_aliases = hostinfo->h_aliases;
for(int j=0;addr_aliases[j]!=NULL;j++)
printf("Aliases: %s\n",addr_aliases[j]);

//print hostinfo->h_addrtype here.
if(hostinfo->h_addrtype == AF_INET)
printf("The type is IPv4.\n");
else if(hostinfo->h_addrtype == AF_INET6)
printf("The type is IPv6.\n");
else
printf("Unknown.\n");

//print hostinfo->h_length here.
printf("the length is:%d \n",hostinfo->h_length);

//print hostinfo->h_addr_list here.
char **addr_list = hostinfo->h_addr_list;
for(int i=0; addr_list[i]!=NULL; i++){
ip = (struct in_addr *)(addr_list[i]);
printf("%s\n", inet_ntoa( *ip ));
}

return 0;
}

运行结果:

1
2
3
4
5
6
[email protected]:~/lab5$ ./hostent www.hanxueying.com
The official name is: www.hanxueying.com
The type is IPv4.
the length is:4
104.24.111.179
104.24.110.179

问:为什么写c程序的时候,一把for循环里的i,j写在里边就报错? error: ‘for’ loop initial declarations are only allowed in C99 mode
答:你把文件名从xxx.c改成xxx.cpp就行了。
学长的教导:在gcc编译的时候加上一个参数-std=c99就可以正常编译那个i,j在for内声明的情况了,而不用修改后缀cpp。

问:inet_ntoa()返回的是指针,拿printf打印指针会是什么效果?
答:几种常见情况如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
int a = 10;
int *p = &a;
char *b = "test";
char c = 'a';
printf("%d \n", a); //输出a的值10
printf("%d \n", p); //输出p的值,因为p是指针,即输出的是a的地址。
printf("%d \n", *p); //输出p指针指向的内容的值。因为p指向了a,所以输出a的值10。
printf("%d \n", b); //输出地址
printf("%s \n", b); //输出内容"test"
printf("%c \n", *b); //输出单个字符't'
/* printf("%s \n", *b); 会crash,因为此时*b是单个字符't' */
//指针变量在声明的时候,例如int *p = &a,并不表示把&a赋给*p,而是表示把&a赋给p,因为*仅表示这是一个指针。
//p是指针变量,即指向a的那个指针;*p是指向内容的值,即a变量实体。

相关原型:

1
2
3
4
5
6
7
8
9
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* pointer to alternate host name array */
int h_addrtype; /* address type */
int h_length; /* length in bytes of address */
char **h_addr_list; /* pointer to array of network addresses */
};

#define h_addr h_addr_list[0] /* the first address in the address list */

1
2
3
4
//inet_ntoa()函数原型:
//defined in <arpa/inet.h>
char * inet_ntoa(struct in_addr inaddr);
//返回值说明:返回一个点分十进制数串的指针

进阶:使用IPv4地址或域名查询

(没考虑管理员没注册导致返回空指针的问题,所以测试用8.8.8.8)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
struct hostent *hostinfo;
struct in_addr address;

if (argc != 2) {
printf("Usage:\n%s hanxueying.com\n", argv[0]);
exit(1);
}else if(inet_aton(argv[1], address) == 1)
hostinfo = gethostbyaddr(&address, sizeof(address), AF_INET);
else if(gethostbyname(argv[1]) != NULL)
hostinfo = gethostbyname(argv[1]);
else{
printf("Neither valid IPv4 address, nor valid domain name.\n");
exit(1);
}

//print hostinfo->h_name here.
printf("The official name is: %s \n",hostinfo->h_name);

//print hostinfo->h_aliases here.
char **addr_aliases = hostinfo->h_aliases;
for(char **aptr=hostinfo->h_aliases; *aptr != NULL; aptr++)
printf("Aliases: %s\n",*aptr);

//print hostinfo->h_addrtype here.
if(hostinfo->h_addrtype == AF_INET)
printf("The type is IPv4.\n");
else if(hostinfo->h_addrtype == AF_INET6)
printf("The type is IPv6.\n");
else
printf("Unknown.\n");

//print hostinfo->h_length here.
printf("The length is:%d \n",hostinfo->h_length);

//print hostinfo->h_addr_list here.
for(char **pptr=hostinfo->h_addr_list; *pptr!=NULL; pptr++){
//printf("%s\n", inet_ntoa(*(struct in_addr *) *pptr ) );
printf("%s\n", inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list));

}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
struct hostent *hostinfo;
struct in_addr address;

if (argc != 2) {
printf("Usage:\n%s hanxueying.com\n", argv[0]);
exit(1);
}else if(inet_aton(argv[1], address) == 1)
hostinfo = gethostbyaddr(&address, sizeof(address), AF_INET);
else if(gethostbyname(argv[1]) != NULL)
hostinfo = gethostbyname(argv[1]);
else{
printf("Neither valid IPv4 address, nor valid domain name.\n");
exit(1);
}

//print hostinfo->h_name here.
printf("The official name is: %s \n",hostinfo->h_name);

//print hostinfo->h_aliases here.
char **addr_aliases = hostinfo->h_aliases;
for(char **aptr=hostinfo->h_aliases; *aptr != NULL; aptr++)
printf("Aliases: %s\n",*aptr);
/*
while ((hostinfo->h_aliases)[0])
printf("Host aliases: %s\n", *hostinfo->h_aliases++);
*/


//print hostinfo->h_addrtype here.
if(hostinfo->h_addrtype == AF_INET)
printf("The type is IPv4.\n");
else if(hostinfo->h_addrtype == AF_INET6)
printf("The type is IPv6.\n");
else
printf("Unknown.\n");

//print hostinfo->h_length here.
printf("The length is:%d \n",hostinfo->h_length);

//print hostinfo->h_addr_list here.
for(char **pptr=hostinfo->h_addr_list; *pptr!=NULL; pptr++){
//printf("%s\n", inet_ntoa(*(struct in_addr *) *pptr ) );
printf("%s\n", inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list));
}
/*
while ((hostinfo->h_addr_list)[0])
printf("IP address: %s\n", inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list++));
*/

return 0;
}

Scan the QR code to add me on Wechat