首页 > 编程语言 >【网络编程开发】16.域名解析与http服务器实现原理

【网络编程开发】16.域名解析与http服务器实现原理

时间:2024-06-15 18:31:37浏览次数:26  
标签:http addr 16 int 域名解析 fd newfd include 请求

16.域名解析与http服务器实现原理

gethostbyname 函数

  1. 原型

    #include <netdb.h>
    struct hostent *gethostbyname(const char *hostname);
    
  2. 功能:获取主机名对应的IP地址

  3. 参数hostname:要查询的主机名。

  4. 返回值

    • 成功时,返回一个指向hostent结构的指针。
    • 失败时,返回NULL。
  5. 注意:使用完该函数后记得使用endhostent函数进行销毁,清理缓冲区。

  6. struct hostent

    • struct hostent {
          char  *h_name;  /* 官方域名 */
          char **h_aliases;  /* 别名*/
          int    h_addrtype;  /* 地址族(地址类型) */
          int    h_length;  /* 地址长度 */
      char **h_addr_list;  /* 地址列表 */
      }
      #define h_addr h_addr_list[0] /* 实现向后兼容性 */
      
    • h_name :主机的正式名称

    • h_aliases:主机的备用名称数组,以 NULL 结尾指针

    • h_addrtype:地址类型;(AF_INETAF_INET6

    • h_length:地址的长度(以字节为单位)

    • h_addr_list:指向主机网络地址的指针数组(按网络字节顺序),由 NULL 指针终止

    • h_addr h_addr_list:中的第一个地址,以实现向后兼容性

  7. 示例

    #include <stdio.h>
    #include <netdb.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    
    int main(int argc, char *argv[])
    {
    	int i;
    /*检查参数*/
    	if(argc < 2){
    		printf("%s <host name>\n", argv[0]);
    		exit(0);
    	}
    /*将域名赋值给结构体*/
    	struct hostent *host = gethostbyname(argv[1]);
    
    /*打印结构体的内容*/
    	for(i = 0; host->h_aliases[i] != NULL; i++){
    		printf("%s\n", host->h_aliases[i]);
    	}
    	printf("Address type:%s\n",
    			host->h_addrtype == AF_INET ? "AF_INET":"AF_INET6");
    
    	for(i = 0; host->h_addr_list[i] != NULL; i++){
    		printf("IP address %d:%s\n", i, inet_ntoa(*(struct in_addr *)host->h_addr_list[i]));
    	}
    	endhostent();//关闭主机信息文件
    	return 0;
    }
    

    运行程序:./test www.baidu.com

    在这里插入图片描述

HTTP的操作过程

在这里插入图片描述

  1. DNS解析:当用户在浏览器中输入URL或点击链接时,浏览器首先需要将域名转换为对应的IP地址。这一过程称为DNS解析。浏览器会向DNS服务器查询该域名对应的IP地址。
  2. 建立TCP连接:获取到IP地址后,浏览器会与服务器建立TCP连接,这一过程涉及到TCP协议的三次握手。这是为了确保数据能够准确、有序地在网络中传输。
  3. 封装HTTP请求数据包:一旦TCP连接建立成功,浏览器会封装一个HTTP请求数据包,其中包含了请求行、请求头和请求体等信息。
  4. 发送HTTP请求:随后,浏览器通过已经建立的TCP连接,向服务器发送HTTP请求。这个请求可能包含对网页文档的请求,或是对图片、CSS、JavaScript等资源的请求。
  5. 服务器处理请求:服务器接收到HTTP请求后,会根据请求的内容进行处理。这包括读取请求的资源、执行相应的脚本等操作。
  6. 服务器返回响应:处理完请求后,服务器会返回一个HTTP响应,其中包括了状态码、响应头和响应体等信息。状态码告诉客户端请求是否成功,或者遇到了何种错误。
  7. 浏览器解析HTML:收到响应后,浏览器开始解析HTML代码,并构建DOM树。同时,浏览器会根据HTML中的标签和属性,请求必要的资源文件,如CSS样式表、JavaScript脚本以及图片等。
  8. 浏览器渲染页面:在取得并解析所有资源文件后,浏览器开始渲染页面。这个过程包括计算每个元素的位置和样式,最终将页面呈现出来。
  9. 关闭TCP连接:一旦服务器发送了请求的数据,通常会主动关闭TCP连接。但在某些情况下,如果响应头信息中包含Connection:keep-alive,则连接仍然保持打开状态,以便后续在同一连接上发送更多请求

实现http

home.html

<html>
<head>
<title>server name</title>
<meta charset="utf-8">
</head>
<body>
<body>
<h1>文档标题</h1>
<p>Hello World!</p>
</body>
</body>
</html>

http-head.txt

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

server.c

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <strings.h>

#define PORT 80
#define BACKLOG 5
#define HTTPFILE "http-head.txt"
#define HTMLFILE "home.html"

int ClientHandle(int newfd);

int main(int argc, char *argv[])
{
	int fd, newfd;
	struct sockaddr_in addr;
	/*创建套接字*/
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0){
		perror("socket");
		exit(0);
	}
	int opt = 1;
	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &opt, sizeof(opt) ))
		perror("setsockopt");

	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = 0;
	/*绑定通信结构体*/
	if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
		perror("bind");
		exit(0);
	}
	/*设置套接字为监听模式*/
	if(listen(fd, BACKLOG) == -1){
		perror("listen");
		exit(0);
	}
	/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
	newfd = accept(fd, NULL, NULL);
	if(newfd < 0){
		perror("accept");
		exit(0);
	}
	ClientHandle(newfd);
	close(fd);
	return 0;
}

int ClientHandle(int newfd){
	int file_fd = -1;
	char buf[BUFSIZ] = {};
	int ret;
/*接收数据*/
	do {
		ret = recv(newfd, buf, BUFSIZ, 0);
	}while(ret < 0 && errno == EINTR);//如果接收到的数据个数小于0,或者错误为非阻塞时未收到数据的标志EINTR
	if(ret < 0){
		perror("recv");
		exit(0);
	}else if(ret == 0){//客户端主动结束
		close(newfd);
		return 0;
	}else{
		printf("=====================================\n");
		printf("%s", buf);
		fflush(stdout);//刷新缓冲区
	}

/*读取文件HTTPFILE的内容并发送*/
	bzero(buf, ret);
	file_fd = open(HTTPFILE, O_RDONLY);
	if(file_fd < 0){
		perror("open");
		exit(0);
	}
	ret = read(file_fd, buf, BUFSIZ);
	printf("%s\n", buf);
	send(newfd, buf, ret, 0);
	close(file_fd);

/*读取文件HTMLFILE的内容并发送*/
	bzero(buf, ret);
	file_fd = open(HTMLFILE, O_RDONLY);
	if(file_fd < 0){
		perror("open");
		exit(0);
	}
	ret = read(file_fd, buf, BUFSIZ);
	printf("%s\n", buf);
	send(newfd, buf, ret, 0);
	close(file_fd);

	close(newfd);
	return 0;
}
  1. 查看ip地址 ifconfig
    在这里插入图片描述

  2. 运行程序 sudo ./server

  3. 打开浏览器输入ip地址

在这里插入图片描述

标签:http,addr,16,int,域名解析,fd,newfd,include,请求
From: https://blog.csdn.net/2201_75563094/article/details/139678784

相关文章

  • Http压缩zip,加密base64发送与获取
    //数据压缩成Zip再发送publicstaticstringZipBasebyte(stringxml){byte[]bytesToCompress=Encoding.GetEncoding("GBK").GetBytes(xml);MemoryStreamms=newMemoryStream();ZipEntryze=newZipEntry("servlets......
  • MAUI Blazor学习16-连续按BACK退出APP
    MAUIBlazor学习16-连续按BACK退出APPMAUIBlazor系列目录MAUIBlazor学习1-移动客户端Shell布局-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习2-创建移动客户端Razor页面-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习3-绘制ECharts图表-SunnyTrudeau......
  • 116. 小欧的卡牌(卡码网周赛第十七期(23年oppo提前批B组笔试真题))
    116.小欧的卡牌(卡码网周赛第十七期(23年oppo提前批B组笔试真题))题目描述小欧有n张卡牌,第i张卡牌的正面写了个数字ai,背面写了个数字bi。小欧对于每张卡牌可以选择一面向上,她希望最终向上的数字之和为3的倍数。你能告诉小欧有多少方案吗?由于答案过大,请对10^9+7......
  • linux中DNS域名解析服务
    DNS系统在网络中的作用就是维护一个地址数据库,其中记录了各种主机域名与IP地址的对应关系,以便为客户程序提供正向或反向的地址查询服务,即正向解析与反向解析。正向解析:根据域名查IP地址,即将指定的域名解析为相对应的IP地址。域名的正向解析是DNS服务器的最基本的功能,也是最常......
  • linux中DNS域名解析服务(后续补充)
    分离解析简介:分离解析的域名服务器实际也是主域名服务器,这里主要是指根据不同的客户端提供不同的域名解析记录。比如来自内网和外网的不同网段地址的客户机请求解析同一域名时,为其提供不同的解析结果。        实验要求:防火墙要么关闭掉,要么添加允许通过条目。以及......
  • 「杂题乱刷」AT_abc161_d
    代码恢复训练2024.6.14.bfs板子题。链接(luogu)链接(atcoder)代码:点击查看代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换题?打cf不要用umap!!!记住,rating是身外之物。该冲正解时冲正解!Problem:算法:思......
  • 【学习笔记】透视HTTP协议(六):发起请求后,处理流程是怎么样子的?
      本文是一篇学习笔记,学习的课程是极客时间的《透视HTTP协议》。透视HTTP协议_HTTP_HTTPS-极客时间(geekbang.org)本文主要描述发起请求后,具体的处理过程。目录一、简述浏览器HTTP请求过程二、详述浏览器HTTP请求过程一、简述浏览器HTTP请求过程示例:在Chrome浏览......
  • 1606 - 求一个两位数倒序的结果
    问题描述请输出一个两位的整数n,倒过来的数,也就是输出这个两位数个位和十位颠倒的结果。比如:整数23倒过来是32,整数18倒过来是81,整数20倒过来是2。输入两位整数n。输出n倒过来的整数。样例输入16输出61以下是C++实现的代码:代码1#include<iostream>u......
  • 4.16
    编写程序实现中文级联菜单,建议可以使用pypinyin或其它扩展库#一、定义菜单内容map_list={'C盘':{"program":{"MicrosoftOffice":\["IntegratedOffice.exe","OfficeClickToRun.exe"\],"MicrosoftSDKs":\[&quo......
  • 利用某些平台(聚合API、百度AI、科大讯飞API)的API接口,利用HTTP协议向服务器发送请求,并
    要使用C语言通过HTTP协议向服务器发送请求并接收响应,你可以使用如libcurl这样的库来发送HTTP请求。libcurl是一个免费且易于使用的客户端URL传输库,支持多种协议,包括HTTP。同时,为了解析服务器响应中的JSON数据,你可以使用cJSON库,这是一个轻量级的JSON解析库。以下是一个简单的示例......