网络编程——http协议
1、TCP/IP 基本知识
一、概念
TCP/IP协议是一个协议的集合,它是由众多的互联网相关联的协议集合的总称。如图

二、TCP/IP分层管理
TCP/IP模型分为5层:应用层,传输层,网络层,数据链路层,物理层。(注意:OSI分层是分为七层的)分层的最大好处,就是各层负责各层的任务,一旦某一块出现问题,则可以直接替换对应的层即可,无需全部更改。
应用层:应用层是我们平时接触最多的层,它的作用就是向用户提供应用服务时通信的活动。比如说http协议,FTP协议,dns(域名解析)等协议,都是在该层
传输层:主要作用是提供处于网络连接中的两台计算机之间的数据传输。如tcp(可靠的传输控制协议),udp(用户数据报协议)。传输单位是报文段。
网络层:网络层用来处理网络中流动的数据包,数据包是网络传输的最小单位。比如我们常用的IP协议,icmp协议,arp协议(通过IP地址得出对应的mac地址)都在该层。
数据链路层:一般用来处理连接硬件部分,如控制网卡,硬件相关的设备驱动。单位是数据帧
物理层:负责数据传输的硬件。比如说光纤等等
三、TCP/IP通信传输流

1、tcp/ip协议进行网络通信时,会通过分层顺序和对方进行通信。发送端从应用层往下走,接收端则从从下往上走。
2、发送端在层与层之间传递数据时,没经过一层,就会打上相应层所属的首部信息。而在接收端层与层之间传递数据时,没经过一层,则会把对应的首部信息消去。这种把数据包装起来的做法,叫做封装。
四、和http关系密切的协议:IP、TCP、DNS
IP:IP位于网络层,它是一种协议的名称。注意和IP地址区分。它主要的作用就是把各种数据包传递给对方。要保证准确的传递到对方手中,其中有两个重要的条件:1、IP地址 2、MAC地址 ,(IP地址可以和Mac地址进行配对,IP地址可以变换,但MAC地址,一般是不会变的)。
TCP:TCP位于传输层,是可靠的传输协议(连接需要三次握手,断开需要四次挥手),它主要是提供可靠的字节流服务。1、字节流服务:为了传输方便,将大块的数据分割以报文段为单位的数据包进行管理。 2、可靠的传输服务:它能够把数据准确可靠的传给对方
DNS服务:该服务是位于应用层的,主要的作用就是解析域名,可以将域名解析出对应的IP地址。
五、各种协议与HTTP协议之间的关系

2、http协议
一、http协议特点
http是位于应用层的一个超文本传输协议,基于tcp/ip通信协议来传递数据的。具有以下特点
1、简单快速:客户端向服务端请求服务时,只需要传递请求方法和路径。由于http协议简单,使得http服务器的程序规模小,因此通信速度快。
2、灵活:http允许传输任意类型的数据对象。正在传输的类型由Content-Type标记。
3、无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求以后,并且收到客户端的应答后,就端开连接了。
4、无状态:http协议是无状态协议,也就是说对事务处理没有记忆能力,缺少状态,如果后续处理需要前面的信息,则必须要重新传递,这样可能导致每次连接传输的数据量增大,但是在服务器不需要先前的数据的时候,就会快的多了。
5、支持B/S,C/S模式
二、http请求报文和响应报文
请求报文:http请求报文主要有请求行,请求头,空行,请求体四部分组成。
1、请求行:由请求方法(HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT),URL和协议版本组成。
2、请求头:为请求报文添加一些信息,由名/值组成
3、空行:请求头的最后会有一个空行,代表请求头部结束,接下来是请求正文,此部分不可少。
4、请求正文
响应报文:http的响应报文由状态行,响应头部,空行,响应体组成
1、状态行:由服务器HTTP协议版本,响应状态码,状态码的文本描述组成
2、响应头部:和请求头一样,由名/值组成
3、请求头的最后会有一个空行,代表请求头部结束,接下来是请求正文,此部分不可少。
4、响应正文
请求方法

请求头信息

响应头

状态码分类

3、https
众所周知,http是不安全的,它有着很大的缺陷,比如通信使用明文,不验证通信方的身份,无法证明报文的正确性等。所以就有了https。https并不是一个新的协议。https全称HTTP over TLS。这个TLS位于传输层的上层,应用层的下层,作为一个安全层而存在。

注:对于TLS和SSL的区别,大家可以自己去学习。在这里,只需要理解为TLS是SSL的升级版本就好。
一、https怎么加密的?
TLS是基于X.509认证的,他假定所有的数字证书都是由一个层次话的数字证书认证机构发出,即CA。他可以通过加密技术(对称加密和非对称加密)对我们传输的数据进行加密。不了解对称加密和非对称加密的朋友,可以看看我以前写的这篇文章:https://www.cnblogs.com/huangjialin/p/9694488.html CA用自己的私钥签发数字证书,数字证书中包含有公钥,然后加密房就可以使用证书中的公钥解密出CA签发的证书,从中拿到合法的公钥。是不是感觉有点懵逼。简单来说,就是我们一般会在本地内置一个CA证书,然后用本地的CA证书中的公钥去解密。拿到合法的公钥,然后就可以用公钥进行加密数据,然后服务端,就可以使用自己的私钥就行解密拿到相关的数据。
注意:如果不内置本地证书可以吗?可以,但是会存在比较大的漏洞,也就是很容易通过中间人攻击,来截获数据,所有,内置本地证书并且及时更新证书,这是一种比较有效的防止中间人攻击的手段。
说了这么多,我们使用代码来解释一下,拿okhttp来做例子。okhttp添加加密证书的过程。
对okHttp进行简单的配置,对OKhttp不熟悉的朋友可以看看这篇文章:https://www.cnblogs.com/huangjialin/p/9469373.html
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.sslSocketFactory() //配置ssl文件
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS);
OkHttpClient okHttpClient = builder.build();
Request request = new Request.Builder()
.get() //设置请求模式
.url("https://www.baidu.com/")
.build(); Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("MainActivity", "-----------onFailure-----------");
} @Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("MainActivity", "----onResponse----" + response.body().toString());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_LONG).show();
}
}); }
});
okhttp提供了一个方法sslSocketFactory(),专门用来设置ssl的。它需要传递一个SSLSocketFactory。
private synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError();
}
}
上面的使用的是默认的SSLSocketFactory,也就是说什么也没有配置,系统提供的。在校验系统服务器的时候,会信任设备内置的100多个证书。那么他是怎么校验的呢?主要是通过TrustManager这个类。在上面代码sslContext.init(null, null, null);中,我们都填了null作为参数,但是这样的话,都没有办法进行证书的校验。我们看看内部源码
public final void init(KeyManager[] km, TrustManager[] tm,
SecureRandom random)
throws KeyManagementException {
contextSpi.engineInit(km, tm, random);
}
private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}, null);
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError();
}
}
实际上这样配置,基本算是完成了。也没错,但是使用系统默认提供的SSLSocketFactory,它会默认设备中内置的100多个证书。基本上是什么证书都信任了,所以,还是存在很大的风险,中间人很容易就攻击了。所以,我们还得自己配置自己的SSL证书。
private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
try {
// 取到证书的输入流 当然这里不一定要这样读取,就看你的证书存放在哪里了,huangjialin.crt是证书的名称
InputStream is = new FileInputStream("huangjialin.crt");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(is);
// 创建 Keystore 包含我们的证书
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null);
keyStore.setCertificateEntry(null, ca);
// 创建一个 TrustManager 仅把 Keystore 中的证书 作为信任的锚点
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
// 用 TrustManager 初始化一个 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
通过我们自定义的SSL,自己设置信任锚点,安全性才会大大的提升。
网络编程——http协议的更多相关文章
- 网络编程TCP协议-聊天室
网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...
- 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法
网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...
- [转]C#网络编程(订立协议和发送文件) - Part.4
本文转自:http://www.tracefact.net/CSharp-Programming/Network-Programming-Part4.aspx 源码下载:http://www.trac ...
- python 网络编程 -- Tcp协议
Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 客户端 大多数连接都是可靠 ...
- java网络编程+通讯协议的理解
参考: http://blog.csdn.net/sunyc1990/article/details/50773014 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很 ...
- 基于网络编程 TCP协议 及 socket 基本语法
socket是什么 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...
- Java网络编程-HTTP协议
HTTP协议的定义 这篇文章暂时不研究HTTP底层的TCP/IP的握手和挥手过程,只从表面的交互流程分析HTTP协议. HTTP英文全称是Hypertext Transfer Protpcol,也就是 ...
- 网络编程——TCP协议
1.TCP程序概述 TCP是一个可靠的协议,面向连接的协议. 实现TCP程序,需要编写服务器和客户端,Java API为我们提供了java.net包,为实现网络应用程序提供类. ServerSocke ...
- 网络编程——TCP协议的三次握手和四次挥手
三次握手原理解析 TCP握手协议在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND ...
随机推荐
- 关于UI设计行业的认识再到认识
相信很多同学和我一样提及到UI行业时,尤其是连门槛都没有踏入半步时,总会一脸茫然. 我也是一样的,我刚接触UI的前半个月,文章读过好多,作品也看过好多,什么"小白入门UI的十大建议啊&quo ...
- shift + 空格 快捷键 使输入法 在全角和半角直接切换。。 但是全角输入一个 空格 ,会造成jsp页面 无法正常解析。。比如 无法获得参数。。
shift + 空格 快捷键 使输入法 在全角和半角直接切换.. 但是全角输入一个 空格 ,会造成jsp页面 无法正常解析....比如 无法获得参数.. 如 <form action=" ...
- 第三次Scrum编码冲刺!!!
第三次冲刺 一.第三次冲刺任务 ! 在已有的基础上实现图书馆管理员对图书信息的查询以及对图书借阅情况的查询. 二.用户故事 本次的用户是图书馆的管理员 用户输入对应的管理员的账号和密码 用户选择图书 ...
- JavaScript中的 prototype 和 constructor
prototype属性 任何js函数都可以用作构造函数, 而构造函数需要用到prototype属性, 因此, 每个js函数F(除了ES5的Function.bind()方法返回的函数外) 都自动拥有 ...
- 使用eclipse创建android项目的时候为什么会生成两个项目
使用eclipse创建android项目的时候为什么会生成两个项目 问题描述: 使用eclipse创建一个Android项目时,发现project列表中会多创建出一个appcompat_v7项目,再创 ...
- 2018.10.14 loj#6003. 「网络流 24 题」魔术球(最大流)
传送门 网络流好题. 这道题可以动态建图. 不难想到把每个球iii都拆点成i1i_1i1和i2i_2i2,每次连边(s,i1),(i2,t)(s,i_1),(i_2,t)(s,i1),(i2, ...
- 2018.08.12 bzoj5301: [Cqoi2018]异或序列(前缀和+莫队)
传送门 简单的异或前缀和处理+莫队统计答案. 惊奇的发现无论开不开long long都能跑过... 代码: #include<bits/stdc++.h> #define N 100005 ...
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...
- 打开子页面及刷新父页面 window.open window.opener.reload()
//打开子页面 var url=children_url;window.open(url) //刷新parent页面 var url=parent_urlfunction refresh(url){ ...
- <%@ include file=""%>与<jsp:include page=""/>
https://www.cnblogs.com/sharpest/p/6117629.html