lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理

目录

1 域名解析

2 如何实现万维网服务器?

2.1 HTTP 的操作过程

2.2 万维网服务器实现


1 域名解析

域名解析gethostbyname函数 

主机结构在 中定义如下:

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:中的第一个地址,以实现向后兼容性

示例

#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
	int i;
	if(argc < 2){
		printf("%s \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;
}

实现效果

lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理_第1张图片

2 如何实现万维网服务器?

2.1 HTTP 的操作过程

HTTP 规定:在 HTTP 客户与 HTTP 服务器之间的每次交互,都由一个 ASCII 码串构成的请求和一个类似的通用互联网扩充,即“类MIME (MIME-like)”的响应组成。

HTTP 报文通常都使用 TCP 连接传送。

lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理_第2张图片

 http连接过程

lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理_第3张图片

 html解释型语言


home

Hello World!


nginx

 打开home.html(firefox ./home.html)

lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理_第4张图片

2.2 万维网服务器实现

nc命令实现步骤

  • 打开终端,nc <本机ip> 80
  • 打开游览器访问本机ip
  • 在终端输入以下内容
HTTP/1.1 200 OK
Content-Type: text/html


home

Hello World!


nginx

代码实现步骤

  • 准备好http头文件
  • 准备好html文件
  • 创建TCP socket
  • 实现client hanlde功能

home.html 



server name




文档标题

Hello World!

 http-head.txt

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

 服务代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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并且信号中断
	if(ret < 0){
		perror("recv");
		exit(0);
	}else if(ret == 0){
		close(newfd);
		return 0;
	}else{
		printf("=====================================\n");
		printf("%s", buf);
		fflush(stdout);
	}

	bzero(buf, ret);
	file_fd = open(HTTPFILE, O_RDONLY);   //http文件
	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);

	bzero(buf, ret);
	file_fd = open(HTMLFILE, O_RDONLY);   //html文件
	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;
}

lv8 嵌入式开发-网络编程开发 20 域名解析与http服务实现原理_第5张图片

 3 练习

1.模拟实现http服务器,并使用浏览器访问。提交浏览器访问你http服务器的截图

你可能感兴趣的:(嵌入式开发,网络,linux)