C language network programming (3) — Connect to Baidu through DNS
First, gethostbyname () function
We now recognize that a computer host usually uses intuitively readable names. For example, Baidu will remember www.baidu.com instead of his IP address. For most applications, it should deal with the name rather than address. If it is easy to remember for a dotted decimal, then when using IPv6, the IP address is not so easy to remember.
The function gethostbyname under Linux is the most basic function to find the host name. If the call is successful, it returns a pointer to the hostent structure, which contains all the IPv4 addresses of the searched host.
The function prototype is as follows:
struct hostent *gethostbyname(const char *name);
The successful call returns the pointer of the hostent structure. The hostent structure is as follows
struct hostent {
char *h_name; /* 正式的主机名 */
char **h_aliases; /* 主机别名列表 */
int h_addrtype; /* 地址类型,AF_INET->IPv4, AF_INET6->IPv6 */
int h_length; /* 地址长度,单位为字节 */
char **h_addr_list; /* 地址对应的所有IP地址列表 */
}
注:一个地址有多个IP对应,比如一个大型网站可能南方,北方,国外等不同的地方都有主机,总之是很多情况,需要多个IP。
Second, programmatically obtain Baidu's IP address
To use the gethostbyname () function, you need to import the header file:
#include <netdb.h>
We directly use gethostbyname () to get the information of Baidu domain name
// 1、使用gethostbyname()获取百度域名的信息
struct hostent *host_ptr = gethostbyname("www.baidu.com");
Then print the message
// 2、打印百度域名的信息
printf("official name:%s \n",host_ptr->h_name); // 正式的主机名
for(i=0; host_ptr->h_aliases[i] != NULL; i++) // 别名
printf("alias name :%s \n",host_ptr->h_aliases[i]);
// 地址类型,AF_INET->IPv4, AF_INET6->IPv6
printf("address type :%s \n",host_ptr->h_addrtype == AF_INET ?"IPv4":"IPv6");
for(i=0; host_ptr->h_addr_list[i] != NULL; i++) // IP地址列表
printf("addr %d :%s \n",i, inet_ntoa( *(struct in_addr*)host_ptr->h_addr_list[i]));
Compile and run the results as follows:
Then we use the ping
command in the terminal , we can see that we also got two IP addresses
Third, connect to Baidu server
Try to connect to Baidu server
// 3、使用socket()函数获取一个TCP客户端socket文件描述符
int tcp_client = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == tcp_client)
{
perror("socket");
return -1;
}
// 4、百度服务端的IP地址和端口,使用第一个ip地址,端口号80
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET; // 设置地址族为IPv4
server_addr.sin_port = htons(80); // 设置地址的端口号信息
server_addr.sin_addr.s_addr = *(in_addr_t*)host_ptr->h_addr_list[0]; // 设置IP地址
// 5、链接到服务器
ret = connect(tcp_client, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
perror("connect");
else
printf("connect result, ret = %d.\n", ret);
Successful connection:
then send a GET request,
// 6. 发送GET请求
char sendbuf[]={"GET / HTTP/1.1\n\n"};
ret = send(tcp_client, sendbuf, strlen(sendbuf),0);
// 7、等待接收服务端发送过来的数据,最大接收1024个字节
char recvbuf[1024] = {0};
ret = recv(tcp_client, recvbuf, sizeof(recvbuf), 0);
// 8、将接收到的数据打印出来
printf("Recvdate: \n%s \n",recvbuf);
Compile, run, and access successfully.
4. Code
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
int main(void)
{
int ret,i=0;
// 1、使用gethostbyname()获取百度域名的信息
struct hostent *host_ptr = gethostbyname("www.baidu.com");
//struct hostent *host_ptr = gethostbyname("www.163.com");//http://www.hfut.edu.cn/
// 2、打印百度域名的信息
printf("official name:%s \n",host_ptr->h_name); // 正式的主机名
for(i=0; host_ptr->h_aliases[i] != NULL; i++) // 别名
printf("alias name :%s \n",host_ptr->h_aliases[i]);
// 地址类型,AF_INET->IPv4, AF_INET6->IPv6
printf("address type :%s \n",host_ptr->h_addrtype == AF_INET ?"IPv4":"IPv6");
for(i=0; host_ptr->h_addr_list[i] != NULL; i++) // IP地址列表
printf("addr %d :%s \n",i, inet_ntoa( *(struct in_addr*)host_ptr->h_addr_list[i]));
// 3、使用socket()函数获取一个TCP客户端socket文件描述符
int tcp_client = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == tcp_client)
{
perror("socket");
return -1;
}
// 4、百度服务端的IP地址和端口,使用第一个ip地址,端口号80
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET; // 设置地址族为IPv4
server_addr.sin_port = htons(80); // 设置地址的端口号信息
server_addr.sin_addr.s_addr = *(in_addr_t*)host_ptr->h_addr_list[0]; // 设置IP地址
// 5、链接到服务器
ret = connect(tcp_client, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
perror("connect");
else
printf("connect success.\n");
// 6. 发送GET请求
char sendbuf[]={"GET / HTTP/1.1\n\n"};
ret = send(tcp_client, sendbuf, strlen(sendbuf),0);
// 7、等待接收服务端发送过来的数据,最大接收1024个字节
char recvbuf[1024] = {0};
ret = recv(tcp_client, recvbuf, sizeof(recvbuf), 0);
// 8、将接收到的数据打印出来
printf("Recvdate: \n%s \n",recvbuf);
// 9、关闭套接字
close(tcp_client);
}