Programación de red en lenguaje C (3): conéctese a Baidu a través de DNS

Programación de red en lenguaje C (3): conéctese a Baidu a través de DNS

Primero, la función gethostbyname ()

Ahora reconocemos que un host de computadora usualmente usa nombres intuitivamente legibles. Por ejemplo, Baidu recordará www.baidu.com en lugar de su dirección IP. Para la mayoría de las aplicaciones, debe tratar con el nombre en lugar de la dirección. Si es fácil de recordar para un decimal con puntos, entonces cuando se usa IPv6, la dirección IP no es tan fácil de recordar.
  La función gethostbyname en Linux es la función más básica para encontrar el nombre de host. Si la llamada se realiza correctamente, devuelve un puntero a la estructura de host, que contiene todas las direcciones IPv4 del host buscado.
El prototipo de la función es el siguiente:

struct hostent *gethostbyname(const char *name);

La llamada exitosa devuelve el puntero de la estructura del servidor. La estructura del servidor es la siguiente

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。

Segundo, obtenga programáticamente la dirección IP de Baidu

Para usar la función gethostbyname (), debe importar el archivo de encabezado:

#include <netdb.h>

Utilizamos directamente gethostbyname () para obtener la información del nombre de dominio Baidu

	// 1、使用gethostbyname()获取百度域名的信息
    struct hostent *host_ptr = gethostbyname("www.baidu.com");

Luego imprime el mensaje

    // 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 y ejecute los resultados de la siguiente manera:
Inserte la descripción de la imagen aquí
luego usamos el pingcomando en la terminal , podemos ver que también tenemos dos direcciones IP
Inserte la descripción de la imagen aquí

Tercero, conéctese al servidor Baidu

Intenta conectarte al servidor Baidu

	// 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);

Conexión exitosa:
Inserte la descripción de la imagen aquí
luego envíe una solicitud GET,

    // 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);

Compilar, ejecutar y acceder con éxito
Inserte la descripción de la imagen aquí
4. Código

#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);
}


Publicado 69 artículos originales · ganó 13 · vistas 5729

Supongo que te gusta

Origin blog.csdn.net/qq_38113006/article/details/105541354
Recomendado
Clasificación