精华内容
下载资源
问答
  • 下面属于应用层协议的是
    千次阅读
    2022-03-26 21:35:30

    应用层协议原理

    研发网络应用程序的核心是写出能够运行在不同的端系统和通过网络彼此通信的程序。
    在Web应用程序中,有两种互相通信的不同的程序:一个是运行在用户主机的浏览器程序,一个是运行在Web的服务器主机上的Web服务器程序。
    在P2P文件共享中,每个参与的主机都有一个程序。

    网络应用程序体系结构

    客户-服务器体系结构

    有一个总是打开的主机称为服务器,服务于来自许多其他成为客户的主机的请求。
    客户通过服务器的固定的、周知的地址(IP地址)向服务器发送请求,Web服务器接收来自客户的请求,向该客户发送所请求的对象作为响应,客户之间不直接通信。
    缺点:对服务器(数据中心)的要求较高,需要大量服务器处理大量请求,并产生互联和宽带费用

    P2P体系结构

    对位于数据中心的专用服务器有最小的(或没有)依赖,应用程序在主机队之间使用直接通信,这些主机被称为对等方。(个人理解是将服务器的压力分摊到各个用户的主机上)
    优点:
    成本较低,不需要较高要求的服务器和带宽。
    挑战:
    1、ISP友好(原来的ISP设计符合下载比上载多,P2P对上载要求同样较高)
    2、安全性(P2P更加开放)
    3、激励(需要使用用户的主机来完成任务)

    进程通信

    一个进程可以被认为是运行在端系统中的一个程序。在两个不同端系统上的进程,通过跨越计算机网络交换报文而相互通信。

    客户和服务器进程

    网络应用程序有成对的进程组成,这些进程通过网络相互发送报文。对于每对进程,进程之一标识为客户,另一个进程标识为服务器。(发起通信的进程被标识为客户,在会话开始时等待联系的进程是服务器)

    进程与计算机网络之间的接口

    多数应用程序是由通信进程对组成,每对中的两个进程互相发送报文。从一个进程向另一个进程发送报文和从网络接收报文必须通过下面的网络。进程通过一个称为套接字的软件接口向网络发送报文和从网络接收报文。
    套接字是同一台主机内应用层和运输层之间的接口,是建立网络应用程序的可编程接口,也称为应用层程序和网络之间的应用程序编程接口。应用程序开发者可以控制套接字在应用层端的一切,但是对该套接字的运输层端几乎没有控制权。(1、选择运输层协议 2、也许能设定几个运输层参数,如最大缓存和最大报文段长度)

    进程寻址

    在一台主机上运行的进程为了向在另一台主机上运行的进程发送分组,接收进程需要有一个地址。为了表示该接收进程,需要定义:
    1、主机的地址
    2、定义在目的主机中的接受进程的标识符(接受套接字)
    在因特网中,主机由其IP地址标识。IP地址是一个32比特的量且它能够唯一的标识该主机。接收进程的标识符是目的地端口号

    可供应用程序使用的运输服务

    套接字是应用程序进程和运输层协议之间的接口。在发送端的应用程序将报文推进该套接字,在套接字的另一侧,运输层协议负责使该报文进入接收进程的套接字。需要选用不同的运输层协议,从四方面对应用程序服务要求分类:可靠数据传输、吞吐量、定时和安全性。

    可靠数据传输

    一个协议能够是应用程序的一端发送的数据正确、完全地交付给该应用程序的另一端,就认为提供了可靠数据传输。有些应用能够容忍数据丢失,如多媒体应用。

    吞吐量

    可用吞吐量就是发送进程能够向接受进程交付比特的速率。因为网络路径的带宽共享,吞吐量将随时间波动,运输层协议能够以特定的速率提供确保的可用吞吐量。具有吞吐量要求的应用程序被称为带宽敏感的应用。

    定时

    运输协议保证从发送到接收低时延

    安全性

    运输协议对数据加密发送,解密交付

    因特网提供的运输服务

    因特网为应用程序提供两个运输层协议,即UDP和TCP

    TCP服务

    包括面向连接服务和可靠数据传输服务。
    面向连接服务:在应用层数据报文开始流动之前,TCP让客户和服务器相互交换运输层控制信息。在握手阶段后,一个TCP连接在两个进程的套接字之间建立了。连接双方的进程可以在此连接上同时进行报文收发。在应用程序结束报文发送时,必须拆除该连接。
    可靠的数据传输服务:无差错、按适当顺序交付所有发送的数据,没有字节的丢失和冗余。
    当发送方和接收方之间的网络出现用拥塞时,TCP的拥塞机制会抑制发送进程(客户或服务器)

    UDP服务

    是一种不提供不必要服务的轻量级运输协议,它仅提供最小服务。无握手过程,提供不可靠数据传输服务,没有拥塞控制机制。

    因特网传输协议所不提供的服务

    目前的因特网运输协议不提供吞吐量或定时保证服务。电子邮件、远程终端访问、Web、文件传输都使用TCP。因特网电话应用通常设计成如果UDP通信失败就使用TCP作为备份

    应用层协议

    应用层协议定义了:
    •交换的报文类型,例如请求报文和响应报文。
    •各种报文类型的语法,如报文中的各个字段及这些字段是如何描述的。
    •字段的语义,即这些字段中包含的信息的含义。
    • 一个进程何时以及如何发送报文,对报文进行响应的规则。

    更多相关内容
  • 应用层协议 ——— HTTP协议

    千次阅读 多人点赞 2022-05-15 20:18:31
    文章目录HTTP协议认识URLurlencode和urldecodeHTTP协议格式HTTP的方法HTTP常见的Header简单的HTTP服务器 HTTP协议 认识URL urlencode和urldecode HTTP协议格式 HTTP的方法 HTTP常见的Header 简单的HTTP服务器

    HTTP协议

    HTTP简介

    HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一个简单的请求-响应协议,HTTP通常运行在TCP之上。

    在编写网络通信代码时,我们可以自己进行协议的定制,但实际有很多优秀的工程师早就已经写出了许多非常成熟的应用层协议,其中最典型的就是HTTP协议。

    认识URL

    URL(Uniform Resource Lacator)叫做统一资源定位符,也就是我们通常所说的网址,是因特网的万维网服务程序上用于指定信息位置的表示方法。

    一个URL大致由如下几部分构成:
    在这里插入图片描述

    一、协议方案名

    http://表示的是协议名称,表示请求时需要使用的协议,通常使用的是HTTP协议或安全协议HTTPS。HTTPS是以安全为目标的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。

    常见的应用层协议:

    • DNS(Domain Name System)协议:域名系统。
    • FTP(File Transfer Protocol)协议:文件传输协议。
    • TELNET(Telnet)协议:远程终端协议。
    • HTTP(Hyper Text Transfer Protocol)协议:超文本传输协议。
    • HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer)协议:安全数据传输协议。
    • SMTP(Simple Mail Transfer Protocol)协议:电子邮件传输协议。
    • POP3(Post Office Protocol - Version 3)协议:邮件读取协议。
    • SNMP(Simple Network Management Protocol)协议:简单网络管理协议。
    • TFTP(Trivial File Transfer Protocol)协议:简单文件传输协议。

    二、登录信息

    usr:pass表示的是登录认证信息,包括登录用户的用户名和密码。虽然登录认证信息可以在URL中体现出来,但绝大多数URL的这个字段都是被省略的,因为登录信息可以通过其他方案交付给服务器。

    三、服务器地址

    www.example.jp表示的是服务器地址,也叫做域名,比如www.alibaba.comwww.qq.comwww.baidu.com

    需要注意的是,我们用IP地址标识公网内的一台主机,但IP地址本身并不适合给用户看。比如说我们可以通过ping命令,分别获得www.baidu.comwww.qq.com这两个域名解析后的IP地址。
    在这里插入图片描述
    如果用户看到的是这两个IP地址,那么用户在访问这个网站之前并不知道这两个网站到底是干什么的,但如果用户看到的是www.baidu.comwww.qq.com这两个域名,那么用户至少知道这两个网站分别对应的是哪家公司,因此域名具有更好的自描述性。

    实际我们可以认为域名和IP地址是等价的,在计算机当中使用的时候既可以使用域名,也可以使用IP地址。但URL呈现出来是可以让用户看到的,因此URL当中是以域名的形式表示服务器地址的。

    四、服务器端口号

    80表示的是服务器端口号。HTTP协议和套接字编程一样都是位于应用层的,在进行套接字编程时我们需要给服务器绑定对应的IP和端口,而这里的应用层协议也同样需要有明确的端口号。

    常见协议对应的端口号:

    协议名称对应端口号
    HTTP80
    HTTPS443
    SSH22

    当我们使用某种协议时,该协议实际就是在为我们提供服务,现在这些常用的服务与端口号之间的对应关系都是明确的,所以我们在使用某种协议时实际是不需要指明该协议对应的端口号的,因此在URL当中,服务器的端口号一般也是被省略的。

    五、带层次的文件路径

    /dir/index.htm表示的是要访问的资源所在的路径。访问服务器的目的是获取服务器上的某种资源,通过前面的域名和端口已经能够找到对应的服务器进程了,此时要做的就是指明该资源所在的路径。

    比如我们打开浏览器输入百度的域名后,此时浏览器就帮我们获取到了百度的首页。
    在这里插入图片描述
    当我们发起网页请求时,本质是获得了这样的一张网页信息,然后浏览器对这张网页信息进行解释,最后就呈现出了对应的网页。
    在这里插入图片描述
    我们可以将这种资源称为网页资源,此外我们还会向服务器请求视频、音频、网页、图片等资源。HTTP之所以叫做超文本传输协议,而不叫做文本传输协议,就是因为有很多资源实际并不是普通的文本资源。

    因此在URL当中就有这样一个字段,用于表示要访问的资源所在的路径。此外我们可以看到,这里的路径分隔符是/,而不是\,这也就证明了实际很多服务都是部署在Linux上的。

    六、查询字符串

    uid=1表示的是请求时提供的额外的参数,这些参数是以键值对的形式,通过&符号分隔开的。

    比如我们在百度上面搜索HTTP,此时可以看到URL中有很多参数,而在这众多的参数当中有一个参数wd(word),表示的就是我们搜索时的搜索关键字wd=HTTP
    在这里插入图片描述
    因此双方在进行网络通信时,是能够通过URL进行用户数据传送的。

    七、片段标识符

    ch1表示的是片段标识符,是对资源的部分补充。

    比如我们在看组图的时候,URL当中就会出现片段标识符。
    在这里插入图片描述
    当我们在翻看组图时,这个片段标识符就会发生变化。
    在这里插入图片描述

    urlencode和urldecode

    如果在搜索关键字当中出现了像/?:这样的字符,由于这些字符已经被URL当作特殊意义理解了,因此URL在呈现时会对这些特殊字符进行转义。

    转义的规则如下:

    • 将需要转码的字符转为十六进制,然后从右到左,取4位(不足4位直接处理),每两位做一位,前面加上%,编码成%XY格式。

    示例

    比如当我们搜索C++时,由于+加号在URL当中也是特殊符号,而+字符转为十六进制后的值就是0x2B,因此一个+就会被编码成一个%2B
    在这里插入图片描述
    说明一下: URL当中除了会对这些特殊符号做编码,对中文也会进行编码。

    在线编码工具

    这里分享一个在线编码工具:

    选中其中的URL编码/解码模式,在输入C++后点击编码就能得到编码后的结果。
    在这里插入图片描述
    再点击解码就能得到原来输入的C++。
    在这里插入图片描述
    实际当服务器拿到对应的URL后,也需要对编码后的参数进行解码,此时服务器才能拿到你想要传递的参数,解码实际就是编码的逆过程。

    HTTP协议格式

    应用层常见的协议有HTTP和HTTPS,传输层常见的协议有TCP,网络层常见的协议是IP,数据链路层对应就是MAC帧了。其中下三层是由操作系统或者驱动帮我们完成的,它们主要负责的是通信细节。如果应用层不考虑下三层,在应用层自己的心目当中,它就可以认为自己是在和对方的应用层在直接进行数据交互。
    在这里插入图片描述
    下三层负责的是通信细节,而应用层负责的是如何使用传输过来的数据,两台主机在进行通信的时候,应用层的数据能够成功交给对端应用层,因为网络协议栈的下三层已经负责完成了这样的通信细节,而如何使用传输过来的数据就需要我们去定制协议,这里最典型的就是HTTP协议。

    HTTP是基于请求和响应的应用层服务,作为客户端,你可以向服务器发起request,服务器收到这个request后,会对这个request做数据分析,得出你想要访问什么资源,然后服务器再构建response,完成这一次HTTP的请求。这种基于request&response这样的工作方式,我们称之为cs或bs模式,其中c表示client,s表示server,b表示browser。

    由于HTTP是基于请求和响应的应用层访问,因此我们必须要知道HTTP对应的请求格式和响应格式,这就是学习HTTP的重点。

    HTTP请求协议格式

    HTTP请求协议格式如下:
    在这里插入图片描述
    HTTP请求由以下四部分组成:

    • 请求行:[请求方法]+[url]+[http版本]
    • 请求报头:请求的属性,这些属性都是以key: value的形式按行陈列的。
    • 空行:遇到空行表示请求报头结束。
    • 请求正文:请求正文允许为空字符串,如果请求正文存在,则在请求报头中会有一个Content-Length属性来标识请求正文的长度。

    其中,前面三部分是一般是HTTP协议自带的,是由HTTP协议自行设置的,而请求正文一般是用户的相关信息或数据,如果用户在请求时没有信息要上传给服务器,此时请求正文就为空字符串。

    如何将HTTP请求的报头与有效载荷进行分离?

    当应用层收到一个HTTP请求时,它必须想办法将HTTP的报头与有效载荷进行分离。对于HTTP请求来讲,这里的请求行和请求报头就是HTTP的报头信息,而这里的请求正文实际就是HTTP的有效载荷。

    我们可以根据HTTP请求当中的空行来进行分离,当服务器收到一个HTTP请求后,就可以按行进行读取,如果读取到空行则说明已经将报头读取完毕,实际HTTP请求当中的空行就是用来分离报头和有效载荷的。

    如果将HTTP请求想象成一个大的线性结构,此时每行的内容都是用\n隔开的,因此在读取过程中,如果连续读取到了两个\n,就说明已经将报头读取完毕了,后面剩下的就是有效载荷了。

    获取浏览器的HTTP请求

    在网络协议栈中,应用层的下一层叫做传输层,而HTTP协议底层通常使用的传输层协议是TCP协议,因此我们可以用套接字编写一个TCP服务器,然后启动浏览器访问我们的这个服务器。

    由于我们的服务器是直接用TCP套接字读取浏览器发来的HTTP请求,此时在服务端没有应用层对这个HTTP请求进行过任何解析,因此我们可以直接将浏览器发来的HTTP请求进行打印输出,此时就能看到HTTP请求的基本构成。
    在这里插入图片描述
    因此下面我们编写一个简单的TCP服务器,这个服务器要做的就是把浏览器发来的HTTP请求进行打印即可。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstring>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    using namespace std;
    
    int main()
    {
    	//创建套接字
    	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    	if (listen_sock < 0){
    		cerr << "socket error!" << endl;
    		return 1;
    	}
    	//绑定
    	struct sockaddr_in local;
    	memset(&local, 0, sizeof(local));
    	local.sin_family = AF_INET;
    	local.sin_port = htons(8081);
    	local.sin_addr.s_addr = htonl(INADDR_ANY);
    	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
    		cerr << "bind error!" << endl;
    		return 2;
    	}
    	//监听
    	if (listen(listen_sock, 5) < 0){
    		cerr << "listen error!" << endl;
    		return 3;
    	}
    	//启动服务器
    	struct sockaddr peer;
    	memset(&peer, 0, sizeof(peer));
    	socklen_t len = sizeof(peer);
    	for (;;){
    		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
    		if (sock < 0){
    			cerr << "accept error!" << endl;
    			continue;
    		}
    		if (fork() == 0){ //爸爸进程
    			close(listen_sock);
    			if (fork() > 0){ //爸爸进程
    				exit(0);
    			}
    			//孙子进程
    			char buffer[1024];
    			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
    			cout << "--------------------------http request begin--------------------------" << endl;
    			cout << buffer << endl;
    			cout << "---------------------------http request end---------------------------" << endl;
    			
    			close(sock);
    			exit(0);
    		}
    		//爷爷进程
    		close(sock);
    		waitpid(-1, nullptr, 0); //等待爸爸进程
    	}
    	return 0;
    }
    

    运行服务器程序后,然后用浏览器进行访问,此时我们的服务器就会收到浏览器发来的HTTP请求,并将收到的HTTP请求进行打印输出。
    在这里插入图片描述
    说明一下:

    • 浏览器向我们的服务器发起HTTP请求后,因为我们的服务器没有对进行响应,此时浏览器就会认为服务器没有收到,然后再不断发起新的HTTP请求,因此虽然我们只用浏览器访问了一次,但会受到多次HTTP请求。
    • 由于浏览器发起请求时默认用的就是HTTP协议,因此我们在浏览器的url框当中输入网址时可以不用指明HTTP协议。
    • url当中的/不能称之为我们云服务器上根目录,这个/表示的是web根目录,这个web根目录可以是你的机器上的任何一个目录,这个是可以自己指定的,不一定就是Linux的根目录。

    其中请求行当中的url一般是不携带域名以及端口号的,因为在请求报头中的Host字段当中会进行指明,请求行当中的url表示你要访问这个服务器上的哪一路径下的资源。如果浏览器在访问我们的服务器时指明要访问的资源路径,那么此时浏览器发起的HTTP请求当中的url也会跟着变成该路径。
    在这里插入图片描述
    而请求报头当中全部都是以key: value形式按行陈列的各种请求属性,请求属性陈列完后紧接着的就是一个空行,空行后的就是本次HTTP请求的请求正文,此时请求正文为空字符串,因此这里有两个空行。

    HTTP响应协议格式

    HTTP响应协议格式如下:
    在这里插入图片描述
    HTTP响应由以下四部分组成:

    • 状态行:[http版本]+[状态码]+[状态码描述]
    • 响应报头:响应的属性,这些属性都是以key: value的形式按行陈列的。
    • 空行:遇到空行表示响应报头结束。
    • 响应正文:响应正文允许为空字符串,如果响应正文存在,则响应报头中会有一个Content-Length属性来标识响应正文的长度。比如服务器返回了一个html页面,那么这个html页面的内容就是在响应正文当中的。

    如何将HTTP响应的报头与有效载荷进行分离?

    对于HTTP响应来讲,这里的状态行和响应报头就是HTTP的报头信息,而这里的响应正文实际就是HTTP的有效载荷。与HTTP请求相同,当应用层收到一个HTTP响应时,也是根据HTTP响应当中的空行来分离报头和有效载荷的。当客户端收到一个HTTP响应后,就可以按行进行读取,如果读取到空行则说明报头已经读取完毕。

    构建HTTP响应给浏览器

    服务器读取到客户端发来的HTTP请求后,需要对这个HTTP请求进行各种数据分析,然后构建成对应的HTTP响应发回给客户端。而我们的服务器连接到客户端后,实际就只读取了客户端发来的HTTP请求就将连接断开了。

    接下来我们可以构建一个HTTP请求给浏览器,鉴于现在还没有办法分析浏览器发来的HTTP请求,这里我们可以给浏览器返回一个固定的HTTP响应。我们就将当前服务程序所在的路径作为我们的web根目录,我们可以在该目录下创建一个html文件,然后编写一个简单的html作为当前服务器的首页。
    在这里插入图片描述
    当浏览器向服务器发起HTTP请求时,不管浏览器发来的是什么请求,我们都将这个网页响应给浏览器,此时这个html文件的内容就应该放在响应正文当中,我们只需读取该文件当中的内容,然后将其作为响应正文即可。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstring>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    using namespace std;
    
    int main()
    {
    	//创建套接字
    	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    	if (listen_sock < 0){
    		cerr << "socket error!" << endl;
    		return 1;
    	}
    	//绑定
    	struct sockaddr_in local;
    	memset(&local, 0, sizeof(local));
    	local.sin_family = AF_INET;
    	local.sin_port = htons(8081);
    	local.sin_addr.s_addr = htonl(INADDR_ANY);
    	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
    		cerr << "bind error!" << endl;
    		return 2;
    	}
    	//监听
    	if (listen(listen_sock, 5) < 0){
    		cerr << "listen error!" << endl;
    		return 3;
    	}
    	//启动服务器
    	struct sockaddr peer;
    	memset(&peer, 0, sizeof(peer));
    	socklen_t len = sizeof(peer);
    	for (;;){
    		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
    		if (sock < 0){
    			cerr << "accept error!" << endl;
    			continue;
    		}
    		if (fork() == 0){ //爸爸进程
    			close(listen_sock);
    			if (fork() > 0){ //爸爸进程
    				exit(0);
    			}
    			//孙子进程
    			char buffer[1024];
    			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
    			cout << "--------------------------http request begin--------------------------" << endl;
    			cout << buffer << endl;
    			cout << "---------------------------http request end---------------------------" << endl;
    			
    #define PAGE "index.html" //网站首页
    			//读取index.html文件
    			ifstream in(PAGE);
    			if (in.is_open()){
    				in.seekg(0, in.end);
    				int len = in.tellg();
    				in.seekg(0, in.beg);
    				char* file = new char[len];
    				in.read(file, len);
    				in.close();
    				
    				//构建HTTP响应
    				string status_line = "http/1.1 200 OK\n"; //状态行
    				string response_header = "Content-Length: " + to_string(len) + "\n"; //响应报头
    				string blank = "\n"; //空行
    				string response_text = file; //响应正文
    				string response = status_line + response_header + blank + response_text; //响应报文
    				
    				//响应HTTP请求
    				send(sock, response.c_str(), response.size(), 0);
    
    				delete[] file;
    			}
    			close(sock);
    			exit(0);
    		}
    		//爷爷进程
    		close(sock);
    		waitpid(-1, nullptr, 0); //等待爸爸进程
    	}
    	return 0;
    }
    

    因此当浏览器访问我们的服务器时,服务器会将这个index.html文件响应给浏览器,而该html文件被浏览器解释后就会显示出相应的内容。
    在这里插入图片描述
    此外,我们也可以通过telnet命令来访问我们的服务器,此时也是能够得到这个HTTP响应的。
    在这里插入图片描述
    说明一下:

    • 实际我们在进行网络请求的时候,如果不指明请求资源的路径,此时默认你想访问的就是目标网站的首页,也就是web根目录下的index.html文件。
    • 由于只是作为示例,我们在构建HTTP响应时,在响应报头当中只添加了一个属性信息Content-Length,表示响应正文的长度,实际HTTP响应报头当中的属性信息还有很多。

    HTTP为什么要交互版本?

    HTTP请求当中的请求行和HTTP响应当中的状态行,当中都包含了http的版本信息。其中HTTP请求是由客户端发的,因此HTTP请求当中表明的是客户端的http版本,而HTTP响应是由服务器发的,因此HTTP响应当中表明的是服务器的http版本。

    客户端和服务器双方在进行通信时会交互双方http版本,主要还是为了兼容性的问题。因为服务器和客户端使用的可能是不同的http版本,为了让不同版本的客户端都能享受到对应的服务,此时就要求通信双方需要进行版本协商。

    客户端在发起HTTP请求时告诉服务器自己所使用的http版本,此时服务器就可以根据客户端使用的http版本,为客户端提供对应的服务,而不至于因为双方使用的http版本不同而导致无法正常通信。因此为了保证良好的兼容性,通信双方需要交互一下各自的版本信息。

    HTTP的方法

    HTTP常见的方法如下:

    方法说明支持的HTTP协议版本
    GET获取资源1.0、1.1
    POST传输实体主体1.0、1.1
    PUT传输文件1.0、1.1
    HEAD获得报文首部1.0、1.1
    DELETE删除文件1.0、1.1
    OPTIONS询问支持的方法1.1
    TRACE追踪路径1.1
    CONNECT要求用隧道协议连接代理1.1
    LINK建立和资源之间的联系1.0
    UNLINK断开连接关系1.0

    其中最常用的就是GET方法和POST方法。

    GET方法和POST方法

    GET方法一般用于获取某种资源信息,而POST方法一般用于将数据上传给服务器。但实际我们上传数据时也有可能使用GET方法,比如百度提交数据时实际使用的就是GET方法。

    GET方法和POST方法都可以带参:

    • GET方法是通过url传参的。
    • POST方法是通过正文传参的。

    从GET方法和POST方法的传参形式可以看出,POST方法能传递更多的参数,因为url的长度是有限制的,POST方法通过正文传参就可以携带更多的数据。

    此外,使用POST方法传参更加私密,因为POST方法不会将你的参数回显到url当中,此时也就不会被别人轻易看到。不能说POST方法比GET方法更安全,因为POST方法和GET方法实际都不安全,要做到安全只能通过加密来完成。

    Postman演示GET和POST的区别

    如果访问我们的服务器时使用的是GET方法,此时应该通过url进行传参,可以在Params下进行参数设置,因为Postman当中的Params就相当于url当中的参数,你在设置参数时可以看到对应的url也在随之变化。
    在这里插入图片描述
    此时在我们的服务器收到的HTTP请求当中,可以看到请求行中的url就携带上了我们刚才在Postman当中设置的参数。
    在这里插入图片描述
    而如果我们使用的是POST方法,此时就应该通过正文进行传参,可以在Body下进行参数设置,在设置时可以选中Postman当中的raw方式传参,表示原始传参,也就是你输入的参数是什么样的实际传递的参数就是什么样的。
    在这里插入图片描述
    此时服务器收到的HTTP请求的请求正文就不再是空字符串了,而是我们通过正文传递的参数。
    在这里插入图片描述
    说明一下:

    • 因为此时响应正文不为空字符串,因此响应报头当中出现了Content-Length属性,表示响应正文的长度。

    TCP套接字演示GET和POST的区别

    要演示GET方法和POST方法传参的区别,就需要让浏览器提交参数,此时我们可以在index.html当中再加入两个表单,用作用户名和密码的输入,然后再新增一个提交按钮,此时就可以让浏览器提交参数了。
    在这里插入图片描述
    我们可以通过修改表单当中的method属性指定参数提交的方法,还有一个属性叫做action,表示想把这个表单提交给服务器上的哪个资源。

    此时当我们用浏览器访问我们的服务器时,就会显示这两个表单。
    在这里插入图片描述
    当前我们是用GET方法提交参数的,当我们填充完用户名和密码进行提交时,我们的用户名和密码就会自动被同步到url当中。
    在这里插入图片描述
    同时在服务器这边也通过url收到了刚才我们在浏览器提交的参数。
    在这里插入图片描述
    如果我们将提交表单的方法改为POST方法,此时当我们填充完用户名和密码进行提交时,对应提交的参数就不会在url当中体现出来,而会通过正文将这两个参数传递给了服务器。
    在这里插入图片描述
    此时用户名和密码就通过正文的形式传递给服务器了。
    在这里插入图片描述
    说明一下:

    • 当我们使用GET方法时,我们提交的参数会回显到url当中,因此GET方法一般是处理数据不敏感的。
    • 如果你要传递的数据比较私密的话你一定要用POST方法,倒不是因为POST方法更安全,实际上GET和POST方法传参时都是明文传送,所以都不安全,但是POST方法更私密,因为POST是通过正文传参的,不会将参数立马回显到浏览器的url框当中的,所以相对更私密。

    HTTP的状态码

    HTTP的状态码如下:

    类别原因短语
    1XXInformational(信息性状态码)接收的请求正在处理
    2XXSuccess(成功状态码)请求正常处理完毕
    3XXRedirection(重定向状态码)需要进行附加操作以完成请求
    4XXClient Error(客户端错误状态码)服务器无法处理请求
    5XXServer Error(服务器错误状态码)服务器处理请求出错

    最常见的状态码,比如200(OK),404(Not Found),403(Forbidden请求权限不够),302(Redirect),504(Bad Gateway)。

    Redirection(重定向状态码)

    重定向就是通过各种方法将各种网络请求重新定个方向转到其它位置,此时这个服务器相当于提供了一个引路的服务。

    重定向又可分为临时重定向和永久重定向,其中状态码301表示的就是永久重定向,而状态码302和307表示的是临时重定向。

    临时重定向和永久重定向本质是影响客户端的标签,决定客户端是否需要更新目标地址。如果某个网站是永久重定向,那么第一次访问该网站时由浏览器帮你进行重定向,但后续再访问该网站时就不需要浏览器再进行重定向了,此时你访问的直接就是重定向后的网站。而如果某个网站是临时重定向,那么每次访问该网站时如果需要进行重定向,都需要浏览器来帮我们完成重定向跳转到目标网站。

    临时重定向演示

    进行临时重定向时需要用到Location字段,Location字段是HTTP报头当中的一个属性信息,该字段表明了你所要重定向到的目标网站。

    我们这里要演示临时重定向,可以将HTTP响应当中的状态码改为307,然后跟上对应的状态码描述,此外,还需要在HTTP响应报头当中添加Location字段,这个Location后面跟的就是你需要重定向到的网页,比如我们这里将其设置为CSDN的首页。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstring>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    using namespace std;
    
    int main()
    {
    	//创建套接字
    	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    	if (listen_sock < 0){
    		cerr << "socket error!" << endl;
    		return 1;
    	}
    	//绑定
    	struct sockaddr_in local;
    	memset(&local, 0, sizeof(local));
    	local.sin_family = AF_INET;
    	local.sin_port = htons(8081);
    	local.sin_addr.s_addr = htonl(INADDR_ANY);
    	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
    		cerr << "bind error!" << endl;
    		return 2;
    	}
    	//监听
    	if (listen(listen_sock, 5) < 0){
    		cerr << "listen error!" << endl;
    		return 3;
    	}
    	//启动服务器
    	struct sockaddr peer;
    	memset(&peer, 0, sizeof(peer));
    	socklen_t len = sizeof(peer);
    	for (;;){
    		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
    		if (sock < 0){
    			cerr << "accept error!" << endl;
    			continue;
    		}
    		if (fork() == 0){ //爸爸进程
    			close(listen_sock);
    			if (fork() > 0){ //爸爸进程
    				exit(0);
    			}
    			//孙子进程
    			char buffer[1024];
    			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
    			cout << "--------------------------http request begin--------------------------" << endl;
    			cout << buffer << endl;
    			cout << "---------------------------http request end---------------------------" << endl;
    			
    			//构建HTTP响应
    			string status_line = "http/1.1 307 Temporary Redirect\n"; //状态行
    			string response_header = "Location: https://www.csdn.net/\n"; //响应报头
    			string blank = "\n"; //空行
    			string response = status_line + response_header + blank; //响应报文
    			
    			//响应HTTP请求
    			send(sock, response.c_str(), response.size(), 0);
    
    			close(sock);
    			exit(0);
    		}
    		//爷爷进程
    		close(sock);
    		waitpid(-1, nullptr, 0); //等待爸爸进程
    	}
    	return 0;
    }
    

    此时运行我们的服务器,当我们用telnet命令登录我们的服务器时,向服务器发起HTTP请求时,此时服务器给我们的响应就是状态码307,响应报头当中是Location字段对应的就是CSDN首页的网址
    在这里插入图片描述
    telnet命令实际上只是一来一回,如果我们用浏览器访问我们的服务器,当浏览器收到这个HTTP响应后,还会对这个HTTP响应进行分析,当浏览器识别到状态码是307后就会提取出Location后面的网址,然后继续自动对该网站继续发起请求,此时就完成了页面跳转这样的功能,这样就完成了重定向功能。

    此时当浏览器访问我们的服务器时,就会立马跳转到CSDN的首页。
    在这里插入图片描述

    HTTP常见的Header

    HTTP常见的Header如下:

    • Content-Type:数据类型(text/html等)。
    • Content-Length:正文的长度。
    • Host:客户端告知服务器,所请求的资源是在哪个主机的哪个端口上。
    • User-Agent:声明用户的操作系统和浏览器的版本信息。
    • Referer:当前页面是哪个页面跳转过来的。
    • Location:搭配3XX状态码使用,告诉客户端接下来要去哪里访问。
    • Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。

    Host

    Host字段表明了客户端要访问的服务的IP和端口,比如当浏览器访问我们的服务器时,浏览器发来的HTTP请求当中的Host字段填的就是我们的IP和端口。但客户端不就是要访问服务器吗?为什么客户端还要告诉服务器它要访问的服务对应的IP和端口?

    因为有些服务器实际提供的是一种代理服务,也就是代替客户端向其他服务器发起请求,然后将请求得到的结果再返回给客户端。在这种情况下客户端就必须告诉代理服务器它要访问的服务对应的IP和端口,此时Host提供的信息就有效了。

    User-Agent

    User-Agent代表的是客户端对应的操作系统和浏览器的版本信息。

    比如当我们用电脑下载某些软件时,它会自动向我们展示与我们操作系统相匹配的版本,这实际就是因为我们在向目标网站发起请求的时候,User-Agent字段当中包含了我们的主机信息,此时该网站就会向你推送相匹配的软件版本。在这里插入图片描述

    Referer

    Referer代表的是你当前是从哪一个页面跳转过来的。Referer记录上一个页面的好处一方面是方便回退,另一方面可以知道我们当前页面与上一个页面之间的相关性。

    Keep-Alive(长连接)

    HTTP/1.0是通过request&response的方式来进行请求和响应的,HTTP/1.0常见的工作方式就是客户端和服务器先建立链接,然后客户端发起请求给服务器,服务器再对该请求进行响应,然后立马端口连接。

    但如果一个连接建立后客户端和服务器只进行一次交互,就将连接关闭,就太浪费资源了,因此现在主流的HTTP/1.1是支持长连接的。所谓的长连接就是建立连接后,客户端可以不断的向服务器一次写入多个HTTP请求,而服务器在上层依次读取这些请求就行了,此时一条连接就可以传送大量的请求和响应,这就是长连接。

    如果HTTP请求或响应报头当中的Connect字段对应的值是Keep-Alive,就代表支持长连接。

    Cookie和Session

    HTTP实际上是一种无状态协议,HTTP的每次请求/响应之间是没有任何关系的,但你在使用浏览器的时候发现并不是这样的。

    比如当你登录一次CSDN后,就算你把CSDN网站关了甚至是重启电脑,当你再次打开CSDN网站时,CSDN并没有要求你再次输入账号和密码,这实际上是通过cookie技术实现的,点击浏览器当中锁的标志就可以看到对应网站的各种cookie数据。
    在这里插入图片描述
    这些cookie数据实际都是对应的服务器方写的,如果你将对应的某些cookie删除,那么此时可能就需要你重新进行登录认证了,因为你删除的可能正好就是你登录时所设置的cookie信息。

    cookie是什么呢?

    因为HTTP是一种无状态协议,如果没有cookie的存在,那么每当我们要进行页面请求时都需要重新输入账号和密码进行认证,这样太麻烦了。

    比如你是某个视频网站的VIP,这个网站里面的VIP视频有成百上千个,你每次点击一个视频都要重新进行VIP身份认证。而HTTP不支持记录用户状态,那么我们就需要有一种独立技术来帮我们支持,这种技术目前现在已经内置到HTTP协议当中了,叫做cookie。

    当我们第一次登录某个网站时,需要输入我们的账号和密码进行身份认证,此时如果服务器经过数据比对后判定你是一个合法的用户,那么为了让你后续在进行某些网页请求时不用重新输入账号和密码,此时服务器就会进行Set-Cookie的设置。(Set-Cookie也是HTTP报头当中的一种属性信息)

    当认证通过并在服务端进行Set-Cookie设置后,服务器在对浏览器进行HTTP响应时就会将这个Set-Cookie响应给浏览器。而浏览器收到响应后会自动提取出Set-Cookie的值,将其保存在浏览器的cookie文件当中,此时就相当于我的账号和密码信息保存在本地浏览器的cookie文件当中。
    在这里插入图片描述
    从第一次登录认证之后,浏览器再向该网站发起的HTTP请求当中就会自动包含一个cookie字段,其中携带的就是我第一次的认证信息,此后对端服务器需要对你进行认证时就会直接提取出HTTP请求当中的cookie字段,而不会重新让你输入账号和密码了。

    也就是在第一次认证登录后,后续所有的认证都变成了自动认证,这就叫做cookie技术。

    内存级别&文件级别

    cookie就是在浏览器当中的一个小文件,文件里记录的就是用户的私有信息。cookie文件可以分为两种,一种是内存级别的cookie文件,另一种是文件级别的cookie文件。

    • 将浏览器关掉后再打开,访问之前登录过的网站,如果需要你重新输入账号和密码,说明你之前登录时浏览器当中保存的cookie信息是内存级别的。
    • 将浏览器关掉甚至将电脑重启再打开,访问之前登录过的网站,如果不需要你重新输入账户和密码,说明你之前登录时浏览器当中保存的cookie信息是文件级别的。

    cookie被盗

    如果你浏览器当中保存的cookie信息被非法用户盗取了,那么此时这个非法用户就可以用你的cookie信息,以你的身份去访问你曾经访问过的网站,我们将这种现象称为cookie被盗取了。

    比如你不小心点了某个链接,这个链接可能就是一个下载程序,当你点击之后它就会通过某种方式把程序下载到你本地,并且自动执行该程序,该程序会扫描你的浏览器当中的cookie目录,把所有的cookie信息通过网络的方式传送给恶意方,当恶意方拿到你的cookie信息后就可以拷贝到它的浏览器对应的cookie目录当中,然后以你的身份访问你曾经访问过的网站。

    SessionID

    单纯的使用cookie是非常不安全的,因为此时cookie文件当中就保存的是你的私密信息,一旦cookie文件泄漏你的隐私信息也就泄漏。

    所以当前主流的服务器还引入了SessionID这样的概念,当我们第一次登录某个网站输入账号和密码后,服务器认证成功后还会服务端生成一个对应的SessionID,这个SessionID与用户信息是不相关的。系统会将所有登录用户的SessionID值统一维护起来。

    此时当认证通过后服务端在对浏览器进行HTTP响应时,就会将这个生成的SessionID值响应给浏览器。浏览器收到响应后会自动提取出SessionID的值,将其保存在浏览器的cookie文件当中。后续访问该服务器时,对应的HTTP请求当中就会自动携带上这个SessionID。
    在这里插入图片描述
    而服务器识别到HTTP请求当中包含了SessionID,就会提取出这个SessionID,然后再到对应的集合当中进行对比,对比成功就说明这个用户是曾经登录过的,此时也就自动就认证成功了,然后就会正常处理你发来的请求,这就是我们当前主流的工作方式。

    安全是相对的

    引入SessionID之后,浏览器当中的cookie文件保存的是SessionID,此时这个cookie文件同样可能被盗取。此时用户的账号和密码虽然不会泄漏了,但用户对应的SessionID是会泄漏的,非法用户仍然可以盗取我的SessionID去访问我曾经访问过的服务器,相当于还是存在刚才的问题。

    • 之前的工作方式就相当于把账号和密码信息在浏览器当中再保存一份,每次请求时都自动将账号和密码的信息携带上,但是账号和密码一直在网当中发送太不安全了。
    • 因此现在的工作方式是,服务器只有在第一次认证的时候需要在网络中传输账号和密码,此后在网络上发送的都是SessionID。

    这种方法虽然没有真正解决安全问题,但这种方法是相对安全的。互联网上是不存在绝对安全这样的概念的,任何安全都是相对的,就算你将发送到网络当中的信息进行加密,也有可能被别人破解。

    不过在安全领域有一个准则:如果破解某个信息的成本已经远远大于破解之后获得的收益(说明做这个事是赔本的),那么就可以说这个信息是安全的。

    引入SessionID后的好处

    • 在引入SessionID之前,用户登录的账号信息都是保存在浏览器内部的,此时的账号信息是由客户端去维护的。
    • 而引入SessionID后,用户登录的账号信息是有服务器去维护的,在浏览器内部保存的只是SessionID。

    此时虽然SessionID可能被非法用户盗取,但服务器也可以使用各种各样的策略来保证用户账号的安全。

    • IP是有归类的,可以通过IP地址来判断登录用户所在的地址范围。如果一个账号在短时间内登录地址发送了巨大变化,此时服务器就会立马识别到这个账号发生异常了,进而在服务器当中清除对应的SessionID的值。这时当你或那个非法用户想要访问服务器时,就都需要重新输入账号和密码进行身份认证,而只有你是知道自己的密码的,当你重新认证登录后服务器就可以将另一方识别为非法用户,进而对该非法用户进行对应的黑名单/白名单认证。
    • 当操作者想要进行某些高权限的操作时,会要求操作者再次输入账号和密码信息,再次确认身份。就算你的账号被非法用户盗取了,但非法用户在改你密码时需要输入旧密码,这是非法用户在短时间内无法做到的,因为它并不知道你的密码。这也就是为什么账号被盗后还可以找回来的原因,因为非法用户无法在短时间内修改你的账号密码,此时你就可以通过追回的方式让当前的SessionID失效,让使用该账号的用户进行重新登录认证。
    • SessionID也有过期策略,比如SessionID是一个小时内是有效的。所以即便你的SessionID被非法用户盗取了,也仅仅是在一个小时内有效,而且在功能上受约束,所以不会造成太大的影响。

    任何事情都有两面性,如果不是这些非法用户的存在,现在的服务器肯定是漏洞百出,只有双方不断进行对抗双方才能不断进步。

    实验演示

    当浏览器访问我们的服务器时,如果服务器给浏览器的HTTP响应当中包含Set-Cookie字段,那么当浏览器再次访问服务器时就会携带上这个cookie信息。

    因此我们可以在服务器的响应报头当中添加上一个Set-Cookie字段,看看浏览器第二次发起HTTP请求时是否会带上这个Set-Cookie字段。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstring>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    using namespace std;
    
    int main()
    {
    	//创建套接字
    	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    	if (listen_sock < 0){
    		cerr << "socket error!" << endl;
    		return 1;
    	}
    	//绑定
    	struct sockaddr_in local;
    	memset(&local, 0, sizeof(local));
    	local.sin_family = AF_INET;
    	local.sin_port = htons(8081);
    	local.sin_addr.s_addr = htonl(INADDR_ANY);
    	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
    		cerr << "bind error!" << endl;
    		return 2;
    	}
    	//监听
    	if (listen(listen_sock, 5) < 0){
    		cerr << "listen error!" << endl;
    		return 3;
    	}
    	//启动服务器
    	struct sockaddr peer;
    	memset(&peer, 0, sizeof(peer));
    	socklen_t len = sizeof(peer);
    	for (;;){
    		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
    		if (sock < 0){
    			cerr << "accept error!" << endl;
    			continue;
    		}
    		if (fork() == 0){ //爸爸进程
    			close(listen_sock);
    			if (fork() > 0){ //爸爸进程
    				exit(0);
    			}
    			//孙子进程
    			char buffer[1024];
    			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
    			cout << "--------------------------http request begin--------------------------" << endl;
    			cout << buffer << endl;
    			cout << "---------------------------http request end---------------------------" << endl;
    
    #define PAGE "index.html" //网站首页
    			//读取index.html文件
    			ifstream in(PAGE);
    			if (in.is_open()){
    				in.seekg(0, in.end);
    				int len = in.tellg();
    				in.seekg(0, in.beg);
    				char* file = new char[len];
    				in.read(file, len);
    				in.close();
    
    				//构建HTTP响应
    				string status_line = "http/1.1 200 OK\n"; //状态行
    				string response_header = "Content-Length: " + to_string(len) + "\n"; //响应报头
    				response_header += "Set-Cookie: 2021dragon\n"; //添加Set-Cookie字段
    				string blank = "\n"; //空行
    				string response_text = file; //响应正文
    				string response = status_line + response_header + blank + response_text; //响应报文
    				
    				//响应HTTP请求
    				send(sock, response.c_str(), response.size(), 0);
    
    				delete[] file;
    			}
    			close(sock);
    			exit(0);
    		}
    		//爷爷进程
    		close(sock);
    		waitpid(-1, nullptr, 0); //等待爸爸进程
    	}
    	return 0;
    }
    

    运行服务器后,用浏览器访问我们的服务器,此时通过Fiddler可以看到我们的服务器发给浏览器的HTTP响应报头当中包含了这个Set-Cookie字段。
    在这里插入图片描述
    同时我们也可以在浏览器当中看到这个cookie,这个cookie的值就是我们设置的2021dragon,此时浏览器当中就写入了这样的一个cookie。
    在这里插入图片描述
    然后我们输入用户名和密码并提交,此时相当于第二次访问我们的服务器,此时通过Fiddler可以看到,由于我们提交表单参数用的是POST方法,因此这里的参数是通过正文的形式提交的,更重要的是第二次的HTTP请求当中会携带上这个cookie信息。
    在这里插入图片描述

    科普HTTPS协议

    HTTPS VS HTTP

    早期很多公司刚起步的时候,使用的应用层协议都是HTTP,而HTTP无论是用GET方法还是POST方法传参,都是没有经过任何加密的,因此早期很多的信息都是可以通过抓包工具抓到的。

    为了解决这个问题,于是出现了HTTPS协议,HTTPS实际就是在应用层和传输层协议之间加了一层加密层(SSL&TLS),这层加密层本身也是属于应用层的,它会对用户的个人信息进行各种程度的加密。HTTPS在交付数据时先把数据交给加密层,由加密层对数据加密后再交给传输层。

    当然,通信双方使用的应用层协议必须是一样的,因此对端的应用层也必须使用HTTPS,当对端的传输层收到数据后,会先将数据交给加密层,由加密层对数据进行解密后再将数据交给应用层。
    在这里插入图片描述
    此时数据只有在用户层(应用层)是没有被加密的,而在应用层往下以及网络当中都是加密的,这就叫做HTTPS。

    对称加密 VS 非对称加密

    加密的方式可以分为对称加密和非对称加密:

    • 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密。
    • 采用公钥和私钥来进行加密和解密,用其中一个密钥进行加密就必须用另一个密钥进行解密,这种加密方法称为非对称加密。

    一般而言,对称加密的效率比非对称加密的效率高。

    对称加密的过程

    对称加密的效率更高,因此双方在进行正常通信时使用的是对称加密。但双方要进行对称加密通信,此时就要去加密方要把密钥给解密方,此时解密方才能对数据进行解密,但加密方把密钥(密钥也是数据)给解密方时也是需要对密钥进行加密的,解密废没法解密就没法拿到密钥,这就变成了鸡生蛋蛋生鸡的问题了。

    这里也不可能让加密方给密钥的时候不进行加密,因为那样全世界都知道这个密钥了,后续加密方的加密也就没有意义了。因此刚开始在进行密钥协商的时候需要用非对称加密。

    对称加密的建立过程如下:

    • 通信双方建立连接的时候,双方就可以把支持的加密算法作协商,协商之后在服务器端形成非对称加密时使用的公钥和私钥,在客户端形成对称加密时使用的密钥。
    • 然后服务器将公钥交给客户端(这个公钥全世界都可以看到),然后客户端用这个公钥对客户端形成的密钥进行加密,将加密后的密钥发送给服务器,服务器拿到后再用它的私钥进行解密,最终服务器就拿到了客户端的密钥。
    • 这时客户端和服务器都有了这个密钥,并且其他人是不知道的,此时客户端和服务器就可以进行对称加密通信了。

    需要注意的是,这里客户端用公钥加密后的密钥只有服务器能够解密,因为在非对称加密当中,数据用公钥加密就必须用私钥解密,而只有服务器才有私钥,其他人都只有公钥。

    简单理解对称加密

    如果你还想知道更多的非对称加密算法,可以了解一下RSA,这是一个基于因式分解的非对称加密算法。

    下面我们简单理解一下对称加密,对称加密最典型的例子就是异或运算。
    在这里插入图片描述
    我们用A异或B得到一个中间值C,此时如果我们采用C异或B就能重新得到A。在这个过程中,A就相当于通信双方想要交互的数据,B就相当于对称加密当中的密钥,C就相当于被密钥加密后的数据,异或运算实际就是一个简单的对称加密算法。

    展开全文
  • Linux下的应用层协议验证 ;实验简要介绍;实验目的;实验设备及软件;实验原理 ;实验内容说明 ;实验内容说明;实验内容说明;实验内容说明;实验步骤;实验步骤;实验步骤;实验步骤;实验步骤;3.POP3的验证 参考下列过程 C: c...
  • 15-传输层协议和应用层协议

    千次阅读 2018-04-28 09:49:32
       PS:针对上一篇tcp协议中说到的端到端服务,这里我们再通过传输层协议和应用层协议之间的关系来加深端到端服务的学习和理解。 1. 传输层协议和应用层层协议的关系   在应用层,我们知道有很多协议,比如...

       PS:针对上一篇tcp协议中说到的端到端服务,这里我们再通过传输层协议和应用层协议之间的关系来加深端到端服务的学习和理解。


    1. 传输层协议和应用层层协议的关系

      在应用层,我们知道有很多协议,比如常见的有http,tfp,telnet等,传输层常见的协议有tcp,udp等。通常在发送数据时,应用层是怎么来把数据发送给指定传输层的协议?而在接收数据时,传输层又是怎么把数据上交给指定的应用层协议来处理的?

      带着这几个问题,我们思考一下传输层的协议是怎么来区分应用层的协议呢?

      通常传输层协议为应用层的每一个协议标识了一个端口号,也就是传输层通过不同的端口号来区分不同的应用层协议,传输层协议和应用层协议之间的关系,如图1所示:

    这里写图片描述
    图1-传输层协议和应用层协议之间的关系

      从图1中不难看出,传输层加了端口号来标识应用层的每个协议,那么我们可以知道传输层协议和传输层协议之间的关系:

    1.HTTP协议默认使用了TCP的80端口号
    2.FTP协议默认使用TCP的21端口号
    3.TELNET协议默认使用了TCP的23端口号
    4.SMTP协议默认使用了TCP的25端口号
    5.DNS协议默认使用了UDP的53端口号
    6.RIP协议默认使用了UDP的520端口号
    7.DHCP协议默认使用了UDP的67端口号

      一般来说这些默认端口号是熟知端口(0 - 1023),由IANA组织已经分配好的,最好不要随意改动,以免出现端口不可用或被占用,造成网络无法通信的情况。

    这里写图片描述
    图2-端口和服务的关系

      在图2中可以看到,服务器上运行了web服务,smtp服务,pop3服务,这三个服务分别使用了不同的协议和服务端端口号与客户端进行通信,另外这三台计算机分别也使用了不同客户端端口号和服务端通信。现在这三台计算机分别要访问服务器上的不同服务,发送了3个数据包。

      A计算机要访问服务器上的web服务,因为服务器上的web服务使用了http协议和80端口跟客户端进行通信,所以A计算机发送的数据包,必须封装服务器的目标地址和服务对应的目标端口号,同时服务器也要通过这个数据包拿到源地址和源端口号,然后和客户端通信,因此我们会看到数据包中封装的这些信息。

      对于B计算机和C计算机都是同理,当服务器收到这三个数据包,会根据数据包中不同的目标端口号交给不同的服务,然后服务器上的服务会根据数据包中不同的源端口号再把数据返回给不同的计算机。

      现在我们基本上明白了,ip地址是用来定位网络上的某一台服务器,而端口号是用来定位服务器上的某一个服务。到这里,相信你对端到端服务有更深的理解了。


    2. 传输层协议和网络层协议的区别

    这里写图片描述
    图3-传输层协议和网络层协议的区别

      简单来说,传输层协议主要用于主机的进程与进程之间的相互通信,而网络层协议主要应用于主机与主机之间的相互通信。


    3. 套接字地址

    这里写图片描述
    图4-套接字地址

      实际上TCP使用“连接”(不仅仅是端口)作为最基本的抽象,同时将TCP连接的端点称为插口,或套接字(socket)。

      前面我们说过TCP协议是通过IP地址+端口号的形式来确定数据发送的目标主机的目标进程。那么套接字和端口,IP地址的关系就是:套接字其实就是IP地址和端口号,比如在网络编程里用套接字来表示ip地址和端口号。


    4. 关于字节号和序号

      不知道大家还有没有印象,之前我们在14-tcp协议中的第三小节(TCP对数据封装过程)简单提到过字节和序号,如果有小伙伴不太理解的话,这里再详细介绍一下字节号和序号。

      字节号:TCP是面向字节流的,因此TCP会对字节数据进行编号,即每一个字节数据都会有一个编号,这个编号就叫字节号,编号的范围是:0 ~ 2^32-1,需要注意的是TCP对字节数据编号不是从0和1开始的,而是根据系统内核机制来随机编号的。

    举个栗子:
      现在主机A随机产生了一个编号为1024的字节号,如果现在主机A要发送一个数据,该数据为6000字节大小,那么该数据的字节号范围为1024 - 7023。

      序号:前面我们说过序号是针对数据段的,由主机发送的这6000字节数据以数据段为单位,封装成多个大小不同的tcp数据段报文在网络中传输。因为序号是基于字节号的,所以tcp协议会给每个tcp数据段报文分配一个序号,而这个序号就是tcp数据段报文的第一个字节的编号(字节号)。

    举个栗子:
      比如现在主机A要发送一个6000字节大小的数据,tcp协议对数据分成5个数据段报文来发送,前4个数据段报文都是1000字节,最后一个报文是2000字节。

    假如第一个字节的编号为110
    那么第一个报文的字节号范围:110 ~ 1109
    第二个报文的字节号范围:1110 ~ 2109
    第三个报文的字节号范围:2110 ~ 3109
    第四个报文的字节号范围:3110 ~ 4109
    第五个报文的字节号范围:4110 - 6109
    到这里,序号已经间接给出来了

    展开全文
  • 应用层协议——原理

    千次阅读 2018-08-30 11:44:34
    应用层协议——原理  应用层协议的实现,只需要写出能够运行在不同的端系统(服务器、手机、电脑等)和通过网络彼此通信的程序。因为网络核心设备(路由器、交换机等,不包括端系统设备)并不在应用层上起作用,只...

    应用层协议——原理

      应用层协议的实现,只需要写出能够运行在不同的端系统(服务器、手机、电脑等)和通过网络彼此通信的程序。因为网络核心设备(路由器、交换机等,不包括端系统设备)并不在应用层上起作用,只在网络层及下面层次起作用,所以不需要为网络核心设备写对应的应用程序,即开发应用程序的时候只需要考虑适配端系统,不需要考虑网络核心设备。

    网络应用程序体系结构

      目前主流的网络应用程序体系结构有两种:客户-服务器体系结构(client-server architecture)对等体系结构(P2P)

    • 客户-服务器体系结构(client-server architecture):客户-服务器体系结构中,至少有一个打开的主机,被称为服务器,它服务来自其他许多称为客户的主机的请求。web应用程序就是一个典型的例子,他总是有至少一个web服务器在运行来响应浏览器的请求。客户-服务器体系结构的一个特征就是服务器具有固定且被知晓的IP地址。
    • 对等体系结构(P2P):P2P体系结构对位于数据中心的专用服务器有最小的(或者没有)依赖。应用程序在间断连接的主机对之间使用直接通信,这些主机对被称为对等方。这些对等方并不为服务提供商所有,为用户控制的台式机、笔记本等所有。因为这种对等方通信不必通过专门的服务器,该体系被称为对等方到对等方

    进程通信

    进程的定义

      在操作系统中,进行通信的实际上是进程(process)而不是程序。一个进程可以被认为是运行在端系统中的一个程序。
      两个不同端系统上的进程,通过跨越计算机网络交换报文而相互通信。发送进程生成并向网络中发送报文;接收进程接收这些报文并可能通过报文发送回去进行响应。
      每对通信进程,我们通常将这两个进程之一标识为客户(client),另一个进程标识为服务器(server)。P2P文件共享的某些应用中,一个进程能够既是客户又是服务器。所以我们可以这样定义客户和服务器进程:在给定的一对进程之间的通信回话场景中,发起通信(即在该会话开始时发起与其他进程的联系)的进程被标识为客户,在会话开始时等待联系的进程是服务器

    进程与计算机网络直接的接口

      进程通过一个称为套接字(socket)的软件接口向网络发送报文和从网络接收报文。套接字是同一台主机内应用层与运输层之间的接口,在发送端的应用程序将报文推进套接字,在该套接字的另一侧,运输层协议负责是该报文进入接收进程的套接字。由于该套接字是建立网络应用程序的可编程接口,因此套接字也称为应用程序和网络之间的应用程序编程接口(Application Programming Interface, API)。应用程序开发者可以控制套接字在应用层的一切,但对改套接字的运输层端几乎没有控制权。开发者对运输层的控制仅限于:①选择运输层协议;②也许能设定几个运输层参数,如最大缓存和最大报文段长度等。一旦开发者选择了一个运输层协议,则应用程序就建立在由该协议提供的运输层服务上。

    进程寻址

      在一台主机上运行的进程为了向在另一台主机上运行的进程发送分组,接收进程需要有一个地址。为了标识改接收进程,需要定义两种信息:①主机的地址;②定义在目的主机中的接收进程的标识符。
      在因特网中,主机由其IP地址(IP address)标识。IP地址是一个32比特的量且能够唯一地标识主机。因为一台主机能够运行多个网络应用,发送报文时,发送进程除了要知道目的地的主机地址外,还需要指定运行在接收主机上的接收进程(接收套接字)。目前比较流行的端口有:Web服务器的80端口、SMTP的25端口等。

    运输服务

    可供应用程序使用的运输服务

      网络中运输层的协议不止一种,开发应用时需要根据需求选择相对应的运输层协议。根据对运输层服务的要求,可以将运输层服务大体分为四类:可靠数据传输吞吐量定时安全性

    可靠数据传输

      有时候数据丢失可能会造成灾难性的后果,所以必须做一些工作以确保由应用程序的一端发送的数据正确、完全地交付给该应用程序的另一端。如果一个协议提供了这样的确保数据交付服务,就认为提供了可靠数据传输(reliable data transfer)。当运输协议提供这种服务时,发送进程只要将其数据传递进套接字,就可以完全相信该数据将能无差错地到达接收进程。
      此外,某些进程不能提供可靠数据传输,由发送进程发送的某些数据可能不能够到达接收进程。这种运输层协议一般用于多媒体应用,如音频、视频等。这些应用能够承受一定量的数据丢失,却并不致命。

    吞吐量

      在沿着一条网络路径上的两个进程之间的通信会话场景中,可用吞吐量就是发送进程能够向接收进程交付的比特速率。因为其他会话将共享沿着该网络路径的带宽,并且因为这些会话将会到达和离开,该可用吞吐量将随时间波动。这就要求运输层协议能够以某种特定的速率提供确保的可用吞吐量,及吞吐量服务。使用这种服务,该应用程序能够请求r比特/秒的确保吞吐量,并且该运输协议能够确保可用吞吐量总是至少为r比特/秒。

    定时

      运输层协议能提供定时保证,如发送方注入进套接字中的每个比特到达接收方的套接字不迟于100ms。这种服务队交互式实时应用程序具有很大的吸引力,如网络电话、网络交互游戏等,这些应用为了有效性而要求数据交付有严格的时间限制。

    安全性

      运输协议能够为应用程序提供一种或多种安全性服务。例如,在发送主机中,运输协议能够加密由发送进程传输的所有数据,在接收主机中,运输层协议能够在数据交付给接收进程之前解密这些数据。运输协议还能提供机密性以外的其他安全性服务,包括数据完整性和端点鉴别。

    因特网提供的运输服务

      因特网(更一般的是TCP/IP网络)为应用程序提供两个运输层协议,即UDPTCP。当为因特网创建一个新的应用时,受限要做出的决定是选择UDP还是TCP。每个协议为调用它们的应用程序提供了不同的服务集合。下表为一些应用程序的服务要求。

    应用数据丢失带宽时间敏感
    文件传输不能丢失弹性
    电子邮件不能丢失弹性
    Web文档不能丢失单行(几kbps)
    因特网电话/视频会议容忍丢失音频(几kbps~1Mbps)、视频(10kbps~5Mbps)是,100ms
    存储音频/视频容忍丢失同上是,几秒
    交互式游戏容忍丢视几kbps~10kbps是,100ms
    即时讯息不能丢失弹性是和不是

    TCP服务

      TCP服务模型包括面向连接服务和可靠数据传输服务。当某个应用程序调用TCP作为运输协议时,该应用程序就能获得来自TCP的两种服务。

    • 面向连接的服务:在应用层数据报文开始流动之前,TCP让客户和服务器互相交换运输层控制信息。这个所谓的握手过程提示客户和服务器,使它们为大量分组的到来做好准备。在握手阶段后,一个TCP连接就在两个进程的套接字之间建立了。这条连接是全双工的,即连接双方的进程可以在此连接上同时进行报文的收发。当应用程序结束报文发送时,必须拆除该连接。
    • 可靠的数据传送服务:通信进程能够依靠TCP,无差错、按适当顺序交付所有发送的数据。当应用程序的一端将字节流传进套接字时,它能够依靠TCP将相同的字节流交付给接收方的套接字,而没有字节的丢失和冗余。

        TCP协议还具有拥塞控制机制,这种服务不一定能为通信进程带来直接好处,但能为因特网带来整体好处。当发送方和接收方之间的网络出现拥塞时,TCP的拥塞控制机制会抑制发送进程(客户或服务器)。

    UDP服务

      UDP是一种不提供不必要服务的轻量级运输协议,它仅提供最小服务。UDP是无连接的,因此在两个进程通信前没有握手过程。UDP协议提供一种不可靠数据传送服务,也就是说,当进程将一个报文发送进UDP套接字时,UDP协议并不保证该报文将到达接收进程。不仅如此,达到接收进程的报文也可能是乱序到达的。
      UDP没有包括拥塞控制机制,所以UDP的发送端可以用它选定的任何速率向其下层(网络层)注入数据。

      下表指出了一些流行的因特网应用所使用的运输协议:

    应用应用层协议支撑的运输协议
    电子邮件SMTP [RFC 5321]TCP
    远程终端访问Telnet [RFC 854]TCP
    WebHTTP [RFC 2616]TCP
    文件传输FTP [RFC 959]TCP
    流式多媒体HTTP (如 YouTube)TCP
    因特网电话SIP [RFC 3261]、RTP [RFC 3550]或专用的(如 Skype)UDP 或 TCP

    因特网运输协议所不提供的服务

      运输层协议服务有可靠数据传输吞吐量定时安全性4个方面的服务。TCP提供了可靠的端到端数据传送,并且TCP在应用层可以很容易地用SSL来加强已提供安全服务。但是,TCP却没有提供吞吐量服务和定时服务,或者说因特网运输协议没有提供这两种服务。

    应用层协议定义

      应用层协议(application-layer protocol)定义了运行在不同端系统上的应用程序进程如何相互传递报文。主要有以下的定义:

    • 交换的报文类型,例如请求报文和响应报文
    • 各种报文类型的语法,如报文中的各个字段及这些字段是如何描述的
    • 字段的语义,即这些字段中包含的信息的含义
    • 一个进程何时以及如何发送报文,对报文进行响应的规则
    展开全文
  • 网络协议 (二) Http vs Https (应用层)

    千次阅读 2022-04-18 12:29:45
    ... ...超文本:也就是网络上的包括文本在内的各式各样的消息。 ...这其实是一种懒政,有状态协议会更加复杂,需要维护历史信息,而且如果客户或服务器失效,会产生状态的不一致,...HTTP 是应用层协议,它以 TCP(传输层)作
  • 文章主要介绍了运输层协议和网络层协议的主要区别
  • 【计算机网络学习笔记15】典型应用层协议 1. 域名系统DNS 1.1 域名系统概述 DNS是域名系统(Domain Name System)的缩写,是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更...
  • 目录一 应用层协议1.1 网络应用程序体系结构CS体系结构P2P体系结构1.2 进程通信客户和服务器进程进程与计算机网络之间的接口进程寻址1.3 可供应用程序使用的运输服务可靠数据传输吞吐量定时安全性1.4 因特网提供的...
  • &2 应用层 - 应用层协议原理

    千次阅读 2022-03-09 10:25:35
    应用层协议原理一、网络应用程序体系结构客户机/服务器 体系结构纯P2P 体系结构客户机/服务器与P2P的混合二、进程通信客户机和服务器进程套接字(socket)进程与套接字关系进程寻址进程识别信息(两部分)用户代理...
  • 应用层协议 在传输层之上,便是应用层。传输层的UDP报文和TCP报文段的数据部分就是应用层交付的数据。 不同类型的网络应用有不同的通信规则,因此应用层协议都是多种多样的,比如DNS、FTP、Telent、SMTP、HTTP、RIP...
  • 因特网电子邮件系统有3个主要组成部分:用户代理、邮件服务器、简单邮件传输协议(SMTP)。 用户代理:允许用户阅读、回复、转发、保存和撰写报文。 邮件服务器:每个接收方在其中的某个邮件服务器上有一个邮箱。一...
  • 一、基于TCP的应用层协议有:SMTP、TELNET、HTTP、FTP 基于UDP的应用层协议:DNS、TFTP(简单文件传输协议)、RIP(路由选择协议)、DHCP、BOOTP(是DHCP的前身)、IGMP(Internet组管理协议) ...
  • 应用层主要包含的协议有:文件传送协议FTP、超文本传送协议HTTP FTP提供交互式的访问,允许客户指明文件的类型与格式,并允许文件具有存取权限。FTP屏蔽了各计算机系统的细节,因而适合于在异构网络中任意计算机...
  • HTTP协议(应用层协议

    千次阅读 2018-08-09 15:48:10
     应用层协议,一方面包含客户端和服务器端需要进行交互的信息,一方面包含如何组织(序列化)以及如何解析信息(反序列化)。 2 自定制协议  我们可以通过一个简单的网络计算器的例子来自定制一个协议,体会其中...
  • TCP/IP协议应用层

    千次阅读 2020-11-11 22:49:24
    **** 应用层协议的实现,只需要写出能够运行在不同的端系统(服务器、手机、电脑等)和通过网络彼此通信的程序。因为网络核心设备(路由器、交换机等,不包括端系统设备)并不在应用层上起作用,只在网络层及下面...
  • 零、基础理论 网络应用是计算机网络存在的理由,如万维网(包含了web冲浪、搜索和电子商务),以及具有...一、应用层协议原理 应用层只在端上存在,因此写的时候只需在端上构建。 网络核心最高管到网络层。 SDN:s...
  • 1、【题目】负责电子邮件传输的应用层协议是选项:A.SMTPB.PPPC.IPD.FTP答案:A解析:暂无解析1、【题目】服务与协议是完全不同的两个概念.下列关于它们的说法错误的是选项:A.协议是水平的.即协议是控制对等实体间...
  • 计算机网络应用层协议分析总结

    千次阅读 2018-01-20 15:13:52
    1、应用层协议原理 1.1、网络应用程序体系结构 C/S结构,有一个总是打开的主机称为服务器,它服务于来自许多其他称为客户机的主机请求。客户机主机既可能有时打开,也可能总是打开。C/S结构之下,客户机之间不直接...
  • 最通俗易懂的网络应用层协议详解

    万次阅读 多人点赞 2017-02-23 17:21:00
    前言其实本文只是讲解从传输层到应用层实现网络消息传递的一个详细流程,至于更底层的网络层和网络接口层,那就不在我的考虑范围内了,事实上那部分机制是不需要你去操心的,除非你想开发操作系统!然后本文打着通俗...
  • 基于UDP的应用层协议:TFTP(简单文件传输协议)、RIP(路由信息协议)、DHCP(动态主机设置协议)、BOOTP(引导程序协议,DHCP的前身)、IGMP(Internet组管理协议) 基于TCP和UDP协议:DNS(域名系统)、ECHO(回...
  • 下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文 件。 凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件。 DL/T 645 多功能电能表通信协议及其备案文件...
  • 应用层协议详解

    千次阅读 2019-07-16 09:39:33
    使用http协议讲解应用层协议 ...然后执行下面的命令,telnet命令本身就是一个应用层协议,它的作用是在两台主机间,建立一个连接,也就是打开两台主机间文本传输的一个通道。"telnet google.com ...
  • 应用层常见的协议及对应的端口号

    万次阅读 多人点赞 2016-04-10 21:51:36
    在TCP/IP模型中,应用层是最高层。应用层包括所有的高层协议,并且不断有新的协议加入。...下面为我们就图片上的应用层协议来进行下简单的介绍: 基于TCP协议的都用C/S方式: **** 一:TELNET (远程登录)
  • TCP和UDP是两个传输层协议,广泛应用于网络中不同主机之间传输数据。对任何程序员来说,熟悉TCP和UDP的工作方式都是至关重要的。这就是为什么TCP和UDP是一个流行的Java编程面试问题。我曾经在各种不同的Java面试中见...
  • 应用层协议汇总 (1)# 文件传输协议(FTP) FTP是因特网上使用得最为广泛的应用层传输协议,允许客户指明文件的类型和格式,并允许文件具有存取权限。 FTP的功能 提供不同种类主机系统(软硬件体系都可以不同)之间的...
  • 应用层协议

    千次阅读 2016-08-24 19:48:32
    下面说几个常用的应用层协议 1. HTTP,超文本传输协议,他是web服务的核心协议,在浏览器和服务器之间进行传输,基于TCP协议,使用80端口,HTTP协议采用的是一个请求应答模式,交互过程基于C/S模式,请求消息中...
  • 应用层常见协议及端口号

    千次阅读 2018-03-19 17:27:05
    在TCP/IP模型中,应用层是最高层。应用层包括所有的高层协议,并且...下面为我们就图片上的应用层协议来进行下简单的介绍: 基于TCP协议的都用C/S方式: 一:TELNET (远程登录) (C/S)(tcp) *概述: 远程...
  • 理解基于 TCP 的应用层通信协议

    千次阅读 2019-07-10 18:08:17
    关于七网络通信的基本原理,特别推荐这篇图文并茂的长文《TCP/IP笔记 - 综述》 TCP 通信基本特征 TCP数据流 特征 1. 消息(结构化数据)被编码成字节流写入 TCP 通道。 2. TCP 通道不能保证字节流一定...
  • 除了上图,如果还能记住该协议的功能就可以解决笔试中99%的网络协议问题,下面介绍应用层的各种协议应用层传输协议 FTP FTP(File Transport Protocol,文件传输协议)是网络上两台计算机传送文件的协议,运行在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 329,826
精华内容 131,930
关键字:

下面属于应用层协议的是