C language network programming (3) — Connect to Baidu through DNS

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:
Insert picture description here
Then we use the pingcommand in the terminal , we can see that we also got two IP addresses
Insert picture description here

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:
Insert picture description here
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.
Insert picture description here
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);
}


Published 69 original articles · won 13 · views 5729

Guess you like

Origin blog.csdn.net/qq_38113006/article/details/105541354