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


    目录

    1 域名解析

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

    2.1 HTTP 的操作过程

    2.2 万维网服务器实现


    1 域名解析

    域名解析gethostbyname函数 

    主机结构在 中定义如下:

    1. struct hostent {
    2. char *h_name; /* 官方域名 */
    3. char **h_aliases; /* 别名*/
    4. int h_addrtype; /* 地址族(地址类型) */
    5. int h_length; /* 地址长度 */
    6. char **h_addr_list; /* 地址列表 */
    7. }
    8. #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:中的第一个地址,以实现向后兼容性

    示例

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. int main(int argc, char *argv[])
    7. {
    8. int i;
    9. if(argc < 2){
    10. printf("%s \n", argv[0]);
    11. exit(0);
    12. }
    13. struct hostent *host = gethostbyname(argv[1]);
    14. for(i = 0; host->h_aliases[i] != NULL; i++){
    15. printf("%s\n", host->h_aliases[i]);
    16. }
    17. printf("Address type:%s\n",
    18. host->h_addrtype == AF_INET ? "AF_INET":"AF_INET6");
    19. for(i = 0; host->h_addr_list[i] != NULL; i++){
    20. printf("IP address %d:%s\n", i, inet_ntoa(*(struct in_addr *)host->h_addr_list[i]));
    21. }
    22. endhostent(); //释放创建出的地址
    23. return 0;
    24. }

    实现效果

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

    2.1 HTTP 的操作过程

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

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

     http连接过程

     html解释型语言

    1. home
    2. Hello World!


    3. nginx

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

    2.2 万维网服务器实现

    nc命令实现步骤

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


    5. nginx

    代码实现步骤

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

    home.html 

    1. server name
    2. "utf-8">
    3. 文档标题

    4. Hello World!

     http-head.txt

    1. HTTP/1.1 200 OK
    2. Content-Type: text/html
    3. Connection: close

     服务代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #define PORT 80
    12. #define BACKLOG 5
    13. #define HTTPFILE "http-head.txt"
    14. #define HTMLFILE "home.html"
    15. int ClientHandle(int newfd);
    16. int main(int argc, char *argv[])
    17. {
    18. int fd, newfd;
    19. struct sockaddr_in addr;
    20. /*创建套接字*/
    21. fd = socket(AF_INET, SOCK_STREAM, 0);
    22. if(fd < 0){
    23. perror("socket");
    24. exit(0);
    25. }
    26. int opt = 1;
    27. if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &opt, sizeof(opt) ))
    28. perror("setsockopt");
    29. addr.sin_family = AF_INET;
    30. addr.sin_port = htons(PORT);
    31. addr.sin_addr.s_addr = 0;
    32. /*绑定通信结构体*/
    33. if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
    34. perror("bind");
    35. exit(0);
    36. }
    37. /*设置套接字为监听模式*/
    38. if(listen(fd, BACKLOG) == -1){
    39. perror("listen");
    40. exit(0);
    41. }
    42. /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
    43. newfd = accept(fd, NULL, NULL);
    44. if(newfd < 0){
    45. perror("accept");
    46. exit(0);
    47. }
    48. ClientHandle(newfd);
    49. close(fd);
    50. return 0;
    51. }
    52. int ClientHandle(int newfd){
    53. int file_fd = -1;
    54. char buf[BUFSIZ] = {};
    55. int ret;
    56. do {
    57. ret = recv(newfd, buf, BUFSIZ, 0);
    58. }while(ret < 0 && errno == EINTR); //小于0并且信号中断
    59. if(ret < 0){
    60. perror("recv");
    61. exit(0);
    62. }else if(ret == 0){
    63. close(newfd);
    64. return 0;
    65. }else{
    66. printf("=====================================\n");
    67. printf("%s", buf);
    68. fflush(stdout);
    69. }
    70. bzero(buf, ret);
    71. file_fd = open(HTTPFILE, O_RDONLY); //http文件
    72. if(file_fd < 0){
    73. perror("open");
    74. exit(0);
    75. }
    76. ret = read(file_fd, buf, BUFSIZ);
    77. printf("%s\n", buf);
    78. send(newfd, buf, ret, 0);
    79. close(file_fd);
    80. bzero(buf, ret);
    81. file_fd = open(HTMLFILE, O_RDONLY); //html文件
    82. if(file_fd < 0){
    83. perror("open");
    84. exit(0);
    85. }
    86. ret = read(file_fd, buf, BUFSIZ);
    87. printf("%s\n", buf);
    88. send(newfd, buf, ret, 0);
    89. close(file_fd);
    90. close(newfd);
    91. return 0;
    92. }

     3 练习

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

  • 相关阅读:
    时间戳转换为日期格式(天,小时,分,秒)
    matlab提取特征(医学图像)
    【15分】E. DS森林叶子编码
    便携式自动气象站让你随时随地掌握天气变化
    Python&JS宏 实现保留样式合并表格后拆分
    SparkCore系列-8、RDD 读写外部数据源
    mybatis 数据库字段为空or为空串 忽略条件过滤, 不为空且不为空串时才需nameParam过滤条件
    求Huffman树的带权路径长度
    PDF格式分析(七十三)——链接注释
    shell语法(一)
  • 原文地址:https://blog.csdn.net/m0_60718520/article/details/133966572