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

目录

1 域名解析

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

2.1 HTTP 的操作过程

2.2 万维网服务器实现


1 域名解析

域名解析gethostbyname函数 

主机结构在 <netdb.h> 中定义如下:

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

实现效果

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

2.1 HTTP 的操作过程

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

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

 http连接过程

 html解释型语言

<html>
<head><title>home</title></head>
<body>
<center><h1>Hello World!</h1></center>
<hr><center>nginx</center>
</body>
</html>

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

2.2 万维网服务器实现

nc命令实现步骤

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

<html>
<head><title>home</title></head>
<body>
<center><h1>Hello World!</h1></center>
<hr><center>nginx</center>
</body>
</html>

代码实现步骤

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

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

 服务代码

#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并且信号中断
	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;
}

 3 练习

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

4IOT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值