C语言网络编程(3)— 通过DNS连接到百度

C语言网络编程(3)— 通过DNS连接到百度

一、gethostbyname()函数

我们现在认知一台计算机主机通常采用直观可读的名字。例如百度我们会记住 www.baidu.com 而不是他的IP地址。对于大多数的应用程序来说应该是处理名字而不是处理地址。如果说对于一个点分十进制来说还好记住,那么当使用IPv6时,IP地址就不是那么好记了。
  而Linux下的函数 gethostbyname是查找主机名最基本的函数。如果调用成功,它就返回一个指向hostent结构的指针,该结构中含有所查找主机的所有IPv4地址。
函数原型如下:

struct hostent *gethostbyname(const char *name);

调用成功返回hostent结构体的指针,hostent结构体如下

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。

二、编程获取百度的IP地址

要使用gethostbyname()函数则需要导入头文件:

#include <netdb.h>

我们直接使用gethostbyname()获取百度域名的信息

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

然后将消息打印出来

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

编译,运行结果如下:
在这里插入图片描述
然后我们在终端使用ping命令,可以看到,我们同样得到了两个IP地址
在这里插入图片描述

三、连接百度服务器

尝试连接到百度服务器

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

连接成功:
在这里插入图片描述
然后发送一个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);

编译,运行,访问成功
在这里插入图片描述
四、代码

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


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值