网络整理一(应用层)

一、应用层的作用:
应用层是体系中最高的一层,直接为用户的应用进程(正在运行的程序)提供服务。
二、应用层的相关协议:
应用层的许多协议是基于客户服务器方式的。客户是服务请求方,服务器是服务提供方。
1.域名系统DNS:一整套从域名映射到IP的系统。

  • 最初,通过互联网信息中心来管理hosts文件,使用hosts文件与IP地址的关系。
    -如果一个新的计算机要接入网络,或者某个计算机IP变更,都需要到信息中心申请变更hosts文件。
    -其他计算机也需要定期下载更新版本的hosts文件才能正确上网。
    那么DNS系统解决了此问题。
    –一个组织的系统管理机构,维护系统内的每个主机的Ip和主机名的对应关系。
    –如果新计算机接入网络,将这个信息注册到数据库中。
    –用户输入域名的时候,会自动查询DNS服务器,由DNS服务器检索数据库,得到对应的ip地址。

  • 因特网的域名结构:
    这里写图片描述
    DNS规定,域名中的标号都由英文字母和数字组成,每一个标号不超过63个字符,也不区分大小写字母。
    一级域名:一般为企业域名,行政区域名,如ac(科研机构),com(工,商金融等企业),edu(教育机构),gov(国家的政府机构),mil(中国的国防机构),net(提供互联网服务的机构),org(非营利的组织)。
    二级域名:公司名,学校名等。
    三级域名:mail。

  • 域名服务器:
    DNS服务器的管辖范围不是以域为单位,而是以“区”为单位,区是DNS服务器实际管辖范围。区可能小于等于域,但一定不可能大于域。
    这里写图片描述
    每一层的域名上都有自己的域名服务器,最顶层的是域名服务器。
    每一级域名服务器都知道下层域名服务器的ip地址.(如不知道,则需向上层请求查询,最多回溯到根域名服务器请求查询,根域名服务器查询的结果返回给该层域名服务器)
    每一级至少设置两个及以上的域名服务器。
  • 域名的解析过程
    -1.递归查询:
    这里写图片描述
    -2.迭代查询:
    这里写图片描述

2.超文本传送协议HTTP
HTTP的特点
HTTP是面向事务的应用层协议,它是万维网上能够可靠的交换文件的重要基础。其端口号为80。HTTP使用了面向连接的TCP作为运输层协议,保证了数据的可靠传输。HTTP不必考虑数据在传输过程中被丢弃后又怎样被重传。

  • HTTP协议本身是无连接的,即是说,虽然HTTP使用了TCP连接,但通信的双方在交换HTTP报文之前不需要建立HTTP连接。
  • HTTP协议是无状态的。即是说同一个客户第二次访问同一个服务器上的页面时,服务器的响应与上一次被访问的相同(假定现在的服务器还没有把该页面更新),因为服务器不记得曾经访问过的客户。该种状态的特性简化了服务器的设计,使服务器更容易支持大量并发的HTTP请求。

HTTP的请求报文与响应报文
这里写图片描述
下面来看看HTTP的请求报文:
下面使用telnet远程登陆www.baidu.com举例
这里写图片描述
HTTP请求报文格式:
这里写图片描述
HTTP请求报文主要由请求行、请求头部、请求正文3部分组成

1.请求行

由3部分组成,分别为:请求方法、URL(见备注1)以及协议版本,之间由空格分隔,

请求方法包括GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE以及扩展方法,当然并不是所有的服务器都实现了所有的方法,部分方法即便支持,处于安全性的考虑也是不可用的

协议版本的格式为:HTTP/主版本号.次版本号,常用的有HTTP/1.0和HTTP/1.1

2.请求头部

请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之间使用冒号分隔

这里写图片描述
3,请求正文

可选部分,比如GET请求就没有请求正文

GET请求示例:
这里写图片描述

POST请求示例:
这里写图片描述

HTTP响应报文格式:

HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
这里写图片描述
响应示例:
这里写图片描述

1.状态行

由3部分组成,分别为:协议版本,状态码,状态码描述,之间由空格分隔

状态代码为3位数字,200~299的状态码表示成功,300~399的状态码指资源重定向,400~499的状态码指客户端请求出错,500~599的状态码指服务端出错(HTTP/1.1向协议中引入了信息性状态码,范围为100~199)

这里列举几个常见的:

这里写图片描述

2.响应头部
与请求头部类似,为响应报文添加了一些附加信息

常见响应头部如下:
这里写图片描述

下面为自己实现的一个HTTP服务器。

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<arpa/inet.h>
#include<stdlib.h>
//./tcp_server 127.0.0.1 8080
void service(int sock,char*ip,int port)
{   
    char buf[1024];//用一个大的缓冲区来放客户端的数据
    while(1){
        buf[0]=0;
        ssize_t s=read(sock,buf,sizeof(buf)-1);
        if(s>0){
            buf[s]=0;
            printf("[%s:%d] say#%s\n",ip,port,buf);
            char bbuf[1024];//写入到该缓冲区中
            const char*hello="<h1>hello world</h1>";
            sprintf(bbuf,"http/1.0 200 ok\ncontent-length:%lu\n\n%s",strlen(hello),hello);//将字符串写成%s的形式存在bbuf内
            write(sock,bbuf,strlen(buf));//将其写入sock
        }
        else if(s==0){//write fd closed
            printf("client [%s:%d]quit!\n",ip,port);
            break;
        }else{
            printf("read error\n");
            break;
        }
    }
}
int main(int argc,char*argv[])
{
    if(argc!=3){
        printf("Usage:%s [ip] [port]\n",argv[0]);
        return 1;
    }
    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0){
        perror("socket");
        return 2;
    }
    struct sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_addr.s_addr=inet_addr(argv[1]);
    local.sin_port=htons(atoi(argv[2]));
    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0){
        printf("bind error\n");
        return 3;
    }
    if(listen(sock,5)<0){//listen sock
        perror("listen");
        return 4;
    }
    struct sockaddr_in peer;
    while(1){
        socklen_t len=sizeof(peer);
        int client_sock=accept(sock,(struct sockaddr*)&peer,&len);
        if(client_sock<0){
            printf("accept error\n");
            continue;
        }
        //sucess
        printf("get a new connect,[%s:%d]\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
        service(client_sock,inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
        close(client_sock);
    }
    return 0;
}

下面为显示的结果:
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/xiaodu655/article/details/80961582
今日推荐