TCP/UDP协议为传输层协议,传输层用于向用户提供可靠的端到端(每个进程都用一个端口号唯一标识)的通信,通过提供流量控制和差错控制保证报文的正确传输。
传输单位是报文段或用户数据报。
主要协议包括TCP协议和UDP协议。
协议 | TCP协议 | UDP协议 |
---|---|---|
简介 | 面向连接的、可靠的传输层协议。传输的数据无差错、不丢失、不重复、按序到达(有流量控制、拥塞控制、提供全双工通信) | 无连接的、不可靠的传输层协议。尽最大努力交付,不保证可靠性 |
连接 | 面向连接(发送数据前三次握手建立连接,发送结束四次挥手释放连接) | 无连接的 |
传输数据 | 面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块) | 面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部) |
交互 | 点对点(一对一) | 一对一,一对多,多对多 |
大小 | TCP首部(开销20字节,包括源端口号、目的端口号等以及确认ACK、同步SYN、终止FIN等用于连接建立与数据传输)+TCP数据部分 | UDP首部开销8字节(包括源端口号、目的端口号等)+UDP数据部分 |
适用情景 | TCP用于在传输层有必要实现可靠传输的情景 | UDP主要用于那些对高速传输和实时性有较高要求的通信或广播通信:1.包总量较少的通信(DNS、SNMP等)2.视频、音频等多媒体通信(即时通信)3.限定于LAN等特定网络中的应用通信4.广播通信(广播、多播) |
传输 | 可靠传输: (1)传输信道无差错,保证传输数据正确; (2)不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据; 可靠性原理: (1)使用三次握手建立TCP连接,四次握手释放TCP连接,保证建立的传输信道是可靠的。 (2)使用连续ARQ协议(超时自动重传:如果一个已经发送的报文段在超时时间内没没有收到确认,那么就重传这个报文段)来保证数据传输的正确性, (3)使用滑动窗口协议来保证接收方能够及时处理所接收到的数据,进行流量控制 (4)使用慢开始、拥塞避免、快重传和快恢复来进行拥塞控制,避免网络拥塞 |
不可靠传输: UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务 并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。 即使是出现网络拥堵的情况,UDP也无法进行流量控制等避免网络拥塞行为。 此外传输途中出现丢包,UDP也不负责重发(发送后不管其是否会到达接收方)。甚至当包的到达顺序出现乱序也没有纠正的功能。 如果需要以上的细节控制,不得不交由采用UDP的应用程序去处理。 |
协议 | FTP、HTTP、POP3、TELNET… | SMTP(网络管理)、DNS(域名转换)、TFTP(文件传输)、NFS(远程文件服务器)、DHCP… |
建立连接时候ACK和SYN可以放在一个报文里发送给客户端。
连接关闭时ACK和FIN一般分开发送。
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从万维网(WWW)Web服务器 传输超文本到 本地客户浏览器 的传输协议。
在Internet上的Web服务器上存放的都是超文本信息,客户机需要通过HTTP协议传输所要访问的超文本信息。
HTTP协议特点:
HTTP在应用层通过报文交互数据,分为请求报文和响应报文,分别用于发送请求&响应请求。
客户端发送的 请求报文 第一行为请求行,包含了方法字段。
请求方法 | 用法 | 说明 |
---|---|---|
OPTIONS | 返回服务器针对特定资源所支持的HTTP请求方法 | 返回:Allow: GET,POST,HEAD等 |
HEAD | 获取报文首部 | 与GET方法类似,但不返回报文实体主体部分。用于确认URL的有效性以及资源更新日期时间等 |
GET | 获取资源 | 当前网络请求中,绝大部分使用GET方法 |
POST | 传输实体主体 | 向指定资源传输数据(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改 |
PUT | 上传文件 | 由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法 PUT /new.html HTTP/1.1 |
DELETE | 删除文件 | 与 PUT 功能相反,并且同样不带验证机制 DELETE /file.html HTTP/1.1 |
TRACE | 追踪路径 | 回显服务器收到的请求,主要用于测试或诊断。 |
GET提交 | POST提交 | |
---|---|---|
作用 | 获取资源 | 传输实体数据 |
参数位置 | 附在URL之后(将数据放在HTTP请求行),以?代表URL结尾,多个参数用&连接。例如:login.action?name=chy&password=123 | 提交的数据放在HTTP报文的请求体中 |
参数长度 | 提交的数据大小有限制(因为浏览器对URL的长度有限制) | 提交的数据没有限制(GET提交的数据会在地址栏中显示,而POST提交,地址不会改变) |
参数形式 | 键值对形式(作为查询字符串) | 表单形式,因此必须将Content-type设置为:application/x-www-form- urlencoded |
参数类型 | 只允许ASCII字符 | 任何类型 |
安全性 | 安全性低 请求参数直接在URL上可见 报文可缓存在浏览器内 |
安全性高 请求参数在HTTP请求数据中 浏览器无缓存 |
应用场景 | 传递小量、不敏感的数据。用于从指定资源请求数据 | 传递大量、敏感数据。用于向指定资源提交数据 |
实例 | GET /bookes/?name=chy&password=123 HTTP/1.1 Host: www.wrox.com User-Agent: Mozilla/5.0 Gecko/20050225 Connection: Keep-Alive |
POST / HTTP/1.1 Host: www.wrox.com User-Agent: Mozilla/5.0 Gecko/20050225 Content-type: application/x-www-form- urlencoded Connection: Keep-Alive name=chy&password=123 |
服务器返回的 响应报文 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果。
状态码 | 类别 | 含义 | 常见类型 |
---|---|---|---|
1xx | Informational(信息性状态码) | 接收的请求正在处理 | |
2xx | Success(成功状态码) | 请求正常处理完毕 | 200:OK |
3xx | Redirection(重定向状态码) | 需要进行附加操作以完成请求 | 304 Not Modified :如果请求报文首部包含例如:If-None-Match,If-Modified-Since等HTTP缓存相关数据 当服务器数据未修改时,则返回304告知客户可以使用缓存数据 |
4xx | Client Error(客户端错误状态码) | 服务器无法处理请求 | 400 Bad Request:请求报文出现语法错误 403 Forbidden:请求被拒绝 404 Not Found:没有找到服务器 |
5xx | Server Error(服务器错误状态码) | 服务器处理请求出错 | 500 Internal Server Error:服务器正在执行请求时内部发生错误 |
有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
首部字段名 | 用法 | 说明 |
---|---|---|
Cache-Control | 指定请求和响应遵循的缓存机制 | 取值一般为no-cache或max-age=XX(XX为整数,表示资源缓存有效期(秒)) |
Content-Type | 请求体/响应体类型 | text/plain:数据以纯文本形式(text/json/xml/html)进行编码,其中不含任何控件或格式字符 application/json(x-www-form-urlencoded):数据被编码为名称/值对。是标准的编码格式,如消息主体是序列化后的JSON字符串 multipart/form-data:数据被编码为一条消息,页上的每个控件对应消息中的一个部分,如文件上传 |
Content-Length | 请求体/响应体长度 | 单位字节 |
Content-Encoding | 请求体/响应体编码格式 | 如gzip,deflate |
Accept | 说明接收的类型。可以多个值,用,分开 | Accept:text/plain,text/html |
Accept-Encoding | 告诉对方我方接受的Content-Encoding | 如gzip,deflate |
ETag | 当前资源的标识 | 与Last-Modified、If-None-Match、If-Modified-Since配合,用于缓存控制 |
首部字段名 | 用法 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体使用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
Cache-Control类型 | 描述 |
---|---|
private | 客户端可缓存 |
public | 客户端和代理服务器均可缓存 |
max-age = xxx | 缓存内容在xxx秒后失效 |
no-cache | 需要使用对比缓存来验证缓存数据 |
no-store | 所有内容均不会缓存,不出发强制缓存与对比缓存 |
为什么比较校验要访问服务器?
服务端在进行标识比较后,只返回header部分,通过状态码通知客户端使用缓存,不再需要将报文主体部分返回给客户端。因此报文大小和请求时间打打减少
cookie & session均是解决HTTP无状态协议的一种记录客户状态的机制。
cookie——客户端的通行证
Cookie 是服务器发送到用户浏览器并保存在本地浏览器的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。
创建过程:
session——服务端的客户档案
除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。
Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。
使用 Session 维护用户登录状态的过程如下:
cookie 与 session 区别
cookie | session | |
---|---|---|
存放位置 | 客户端 | 服务端 |
存储数据 | 只能存储 ASCII 码字符串 | 可以存储任何类型数据(考虑存储数据的复杂性) |
安全性 | 低(存储在浏览器中,对用户可见,容易被恶意查看、修改) | 高(session存储在服务器上,不存在敏感信息泄露的风险) |
开销 | 较小 | 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。 |
协议 | HTTP1.0 | HTTP1.X | HTTP2.0 |
---|---|---|---|
特点 | 无状态、无连接 HTTP1.0规定浏览器和服务器保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器处理完成后立即断开TCP连接(无连接),服务器不跟踪每个客户端也不记录过去的请求(无状态)。 |
1. 持久连接:通过请求管道化实现,多个http 请求可以复用一个TCP连接,服务器端按照FIFO原则来处理不同的Request(实现"并行"传输) 2. 缓存处理:cache-control 3. 一个服务器能够创建多个Web站点:Host 4. 断点续传、身份认证、状态管理等 |
1. 二进制分帧:在应用层和传输层之间增加一个二进制分帧,在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段的情况下, 解决了HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量 2. 实现多路复用:多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。即HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流,实现真正的并行传输 3. 头部压缩 4. 服务器推送:是一种在客户端请求之前发送数据的机制。 |
痛点 | 连接无法复用:每次请求都要经历三次握手和慢启动 队头阻塞:由于HTTP1.0规定下一个请求必须在前一个请求响应到达之前才能发送。假设前一个请求响应一直不到达,那么下一个请求就不发送,同样的后面的请求也给阻塞了 |
请求管道化并没有真正地实现"并行",且在 HTTP/1.1 协议中浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞 |
图1为短连接(http 1.0),图2为持久连接(多路复用 http 2.0),图3为持久连接(管道化http 1.1)
报文摘要:用于对发送的报文生成一个非常小的摘要信息。这个摘要信息保证原报文的完整性,即原报文只要有一位被改变,则摘要信息就会不匹配。
服务端,都有公钥、私钥和证书:
证书用来对通信方进行身份认证的。一般证书包含公钥以及身份认证信息。这里的证书可以是向某个权威机构申请的,也可以是自制的。区别在于自己办法的证书需要客户端验证通过,才可以继续访问;而使用受信任的公司申请的证书则不会弹出提示页面。
数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。
服务器的运营人员向 CA 提出公开密钥的申请,CA 在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公开密钥证书后绑定在一起。
进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
HTTP | HTTPS | |
---|---|---|
定义 | 超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议 | HTTPS是身披SSL外壳的HTTP。HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性 |
成本 | 成本低 | 服务器的运营人员需要向CA申请证书,SSL的专业证书需要购买,功能越强大,费用越高 |
安全性 | 安全性较低 | HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全,防止数据在传输过程中被窃取,确保数据的完整性 |
端口 | 80 | 443 |
效率 | 效率较高 | 因为需要进行加密解密等过程,因此速度会更慢 |
加密算法 | 对称加密 | 非对称加密 |
---|---|---|
原理 | 加密算法是公开的,靠的是密钥来加密数据。使用一个密钥加密,使用相同的密钥才能解密 | 加密算法是公开的,有一个公钥,一个私钥(公钥和私钥不是随机的,由加密算法生成);公钥加密只能私钥解密,私钥加密只能公钥解密,加密解密需要不同密钥 |
常用算法 | DES,3DES,AES | RSA |
优点 | 计算量小,加密和解密速度较快,适合加密较大数据 | 可以传输公钥(服务器—>客户端)和公钥加密的数据(客户端->服务器),数据传输安全 |
缺点 | 在传输加密数据之前需要传递密钥,密钥传输容易泄露;一个用户需要对应一个密钥,服务器管理密钥比较麻烦 | 计算量大,加密和解密速度慢 |
Socket 即 套接字,是通信的基石,是应用层 与 TCP/IP 协议族通信的中间软件抽象层,本质为一个封装了 TCP / IP协议族 的编程接口(属于传输层)。网络上的两个进程端口通过Socket实现一个双向的通信连接从而进行数据交换。
Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}
ServerSocket:服务器端类
Socket:客户端类
服务器和客户端通过 InputStream 和 OutputStream 进行输入输出。
(1)连接过程
ServerSocket ss =new ServerSocket(30000);
Socket s = ss.accept();
Socket s = new Socket("192.168.1.88",30000);
(2)通信过程
(1)使用 ServerSocket 创建服务端
public class SocketServer {
public static void main(String[] args) throws IOException {
//1. 创建一个服务器端Socket,即ServerSocket对象,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(12345);
InetAddress address = InetAddress.getLocalHost();
String ip = address.getHostAddress();
Socket socket = null;
//2. 调用accept()等待客户端连接
System.out.println("~~~服务端已就绪,等待客户端接入~,服务端ip地址: " + ip);
socket = serverSocket.accept();
//3. 连接建立后,通过输入流InputStream读取接收到的数据
InputStream is=null;
InputStreamReader isr=null;
BufferedReader br=null;
//4. 通过输出流OutputStream向客户端发送响应信息
OutputStream os=null;
PrintWriter pw=null;
is = socket.getInputStream(); //获取输入流
isr = new InputStreamReader(is,"UTF-8");
br = new BufferedReader(isr);
String info = null;
while((info=br.readLine())!=null){
//循环读取客户端的信息
System.out.println("客户端发送过来的信息" + info);
}
socket.shutdownInput();//关闭输入流
//5. 调用close()方法关闭相关资源
socket.close();
}
}
(2)使用 Socket 创建客户端
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_accept = (Button) findViewById(R.id.btn_accept);
btn_accept.setOnClickListener(this);
}
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
try {
acceptServer();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
private void acceptServer() throws IOException {
//1. 创建客户端Socket,指定服务器ip地址和端口
Socket socket = new Socket("172.16.2.54", 12345);
//2. 连接建立后,通过输出流OutputStream向服务器发送请求信息
//3. 通过输入流InputStream获取服务器响应的信息
OutputStream os = socket.getOutputStream();//字节输出流
PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
// 获取客户端的IP地址
InetAddress address = InetAddress.getLocalHost();
String ip = address.getHostAddress();
pw.write("客户端:~" + ip + "~ 接入服务器!!");
pw.flush();
socket.shutdownOutput();//关闭输出流
//4. 调用close()方法关闭套接字
socket.close();
}}
}}
WebSocket是HTML5一种新的协议。它借鉴了Socket这种思想,为web应用程序客户端和服务端之间(注意是客户端服务端)提供了一种全双工通信机制(full-duplex)。同时,它又是一种新的应用层协议。一开始的握手需要借助HTTP请求完成。
WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。连接过程需要进行握手:
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
function WebSocketTest()
{
if ("WebSocket" in window) // 浏览器支持WebSocket
{
// 打开一个 web socket
// Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:
// ws://example.com/wsapi Websocket与HTTP使用相同的TCP端口:80端口
// wss://secure.example.com/ 运行TLS上时,默认使用443端口
var ws = new WebSocket("ws://localhost:9998/echo");
ws.onopen = function()
{
ws.send("发送数据");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
};
ws.onclose = function()
{ // 连接关闭
};
}
}
Socket | WebSocket | HTTP | |
定义 | 封装了 TCP / IP协议族 的编程接口(API) | 借鉴了Socket这种思想,为web服务器和浏览器之间提供了一种全双工通信机制的数据传输协议 | 利用TCP在Web服务器和浏览器之间数据传输的协议 |
工作层 | 传输层 | 应用层 | |
数据传输 | 全双工通信机制(双向) 即建立网络连接后,通信双方都能主动向对方发送或接受数据,直到双方连接断开。即服务器可主动发送消息给客户端,实现信息的主动推送;而不需要由客户端向服务器发送请求 |
请求-响应(单向) 客户端向服务端发送请求后,服务端才能向客户端返回数据 |
|
持久性 | 持久化 (Socket 的 TCP 长连接的通讯模式:一旦 Socket 连接建立后,后续数据都以帧序列的形式传输。在客户端或服务端断开Socket 连接前,不需要客户端和服务端重新发起连接请求。) |
非持久化 | |
连接建立 & 数据传输 | 1. 创建ServerSocket对象,绑定监听的端口 2. 调用accept()方法监听客户端的请求 3. 连接建立后,通过输入流InputStream、OutputStream进行数据交互 |
TCP连接建立后,借助HTTP协议进行WebSocket三次握手,之后数据传输使用WebSocket协议 | TCP连接建立后,客户端发送请求报文,服务端返回响应报文 |
序列化:把java对象转化为二进制字节码写入IO流中。
反序列化:将IO流中的二进制字节恢复成java对象。
序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
应用场景:
通常建议:程序创建的每个JavaBean类都实现Serializeable接口
{
"name": "中国",
"province": [{
"name": "黑龙江",
"cities": {
"city": ["哈尔滨", "大庆"]
}
}, {
"name": "广东",
"cities": {
"city": ["广州", "深圳", "珠海"]
}
}]
}
解析方式 | JSONObject | FastJson | Gson |
---|---|---|---|
介绍 | 原生 | 阿里巴巴FastJson是一个Json处理工具包 | GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库 |
序列化 | String jsonStr = jsonObject.toString(); String jsonStr = jsonArray.toString(); |
String jsonString = JSON.toJSONString(person); | String gsonString = gson.toJson(object); |
反序列化 | JSONObject jsonObject = new JSONObject(jsonStr); JSONArray jsonArray = new JSONArray(jsonStr); |
person =JSON.parseObject(jsonString,Person.class); List persons2 = JSON.parseArray(jsonString,Person.class); |
T t = gson.fromJson(gsonString, cls); |
特点 | 性能好,速度快 | 功能全面 |
中国
黑龙江
哈尔滨
大庆
广东
广州
深圳
珠海
Android主要提供了两种方式进行网络请求:HttpClient与HttpUrlConnection。
HttpClient | HttpUrlConnection | |
相同 | 都支持https协议,以流的形式进行上传和下载、配置超时事件、IPV6、以及连接池等功能。 | |
不同 | 拥有众多API,实现较稳定,bug数量少。但难以扩展,维护成本高。Android6.0后被移除。 | 提供简单、轻量级API,易于扩展。但Android2.2前有个重大bug。2.3后修改了bug并且提供了压缩和缓存机制,有效提升了网络性能。 |