本系列文章对整个Android网络编程进行了总结,包括基本的TCP/IP协议,HTTP协议,HTTPS协议,HttpClient,UrlConnection,一些网络通信的库到棉花糖新加入的OKHTTP。

本文主要对TCP协议的连接管理和拥塞控制两部分知识进行总结。

连接管理

TCP协议是传输层的重要协议,负责端到端的通信。为了实现面向连接的可靠传输,TCP协议使用“三次握手”和“四次挥手”的方式来创建连接,结束连接。

三次握手:

    • 第一次握手:建立连接时,客户端C发起建立连接请求(SYN=1)到服务器S,并进入SYN_SEND状态,等待服务器返回确认。
    • 第二次握手:服务器S收到客户端C发来的连接请求后,返回确认报文(SYN=1,ACK),并进入SYN_RECV状态。
    • 第三次握手:客户端C收到服务器S发来的确认报文后,也要返回一个确认(SYN=0,ACK),进入ESTABLISHED状态,开始传送数据。

这里需要提一下的是确认号数值ACK=期望对方下次发来的字节序号。

当需要断开连接时候,采用“四次挥手”的方式:

    • 第一次挥手:客户端C发送完数据后,发起释放连接请求(FIN=1),表示要关闭数据传送,进入FIN_WAIT1状态。
    • 第二次挥手:服务端S收到请求后,会继续发送之前未发完的数据(ACK)并进入CLOSE_WAIT状态,关闭读通道,也就是不能再从这个链接上读取数据。C收到对自己释放连接请求的ACK后,关闭写通道,不再向连接中写数据,进入FIN_WAIT2状态。
    • 第三次挥手:服务端S发送完要发送的数据后,发送会关闭写通道(FIN=1)报文,进入LAST_ACK状态。而此时客户端接到该报文后,关闭读通道,进入TIME_WAIT状态。
    • 第四次挥手:客户端C发送对上一步服务器的FIN报文的ACK,然后在等待2个MSL的时间后,进入CLOSED状态。而服务器S在收到该ACK后也进入CLOSED状态。

关于连接建立和释放过程中,有两个状态需要说明一下:

    • SYN_RECV:服务器S收到了来自客户端的建立连接请求,此时称为半连接状态,存储在服务器端的一个半连接队列中。当收到C发来的ACK报文后,会在该队列中查找并移除。如果受到flood SYN攻击,半连接队列溢出,后续连接请求则会被丢弃。可以通过SYN Cookie来防止flood SYN攻击。
    • TIME_WAIT:客户端C在发送对服务器S的FIN报文的确认ACK后,进入了TIME_WAIT状态。客户端会维持这个状态2MSL后才释放socket。这个机制从逻辑上保证了重新被分配的socket不会受到之前残留的延迟重发报文的影响。如果直接关闭客户端C,假如服务器S并未收到C对之前FIN报文的确认,则会重新发送FIN报文给C,但是此时C已经CLOSED了,无法找到此连接只好返回RST(reset)给S。这样虽然没有数据丢失,但是不符合可靠连接的要求。另外,如果C直接关闭后,又重新向server建立了一个连接,端口号又相同,但是之前上一个socket有些滞留数据也会发送到server。这时,服务器就会认为这些滞留数据是新连接发来的,产生混淆。等待2MSL可以保证这些数据消失。

拥塞控制与流量控制

拥塞控制就是防止过多数据注入到网络中,这样可以使网络中的路由器和链路不至于过载。它是一个全局性的过程,涉及到链路上所有的主机和路由器。而流量控制是点对点通信量的控制,是为了防止发送端数据发送过快接收端来不及接收。TCP协议采用慢开始、拥塞避免、快重传以及快恢复的算法进行拥塞控制。发送端维持了一个称为“拥塞窗口”的状态变量cwnd,它随着网络拥塞程度动态变化,这里我们先不去考虑流量控制以及接收方的接收能力,而是让发送方的发送窗口等于拥塞窗口。

慢开始和拥塞避免算法

当主机开始发送数据的时候并不知道网络负荷状况,所以由小到大逐渐增大发送窗口,即由小到大增大拥塞窗口cwnd。初始设置cwnd=1MSS,发送一个报文给接收方。接收方收到该报文后,会返回确认。发送方每次收到一个对新报文段的确认,就将cwnd增加1.因此,慢开始算法每经过一个传输轮次RTT,拥塞窗口加倍:1,2,4…所以说“慢开始”不是说cwnd增长速度慢,而是说在开始发送的时候cwnd=1进行网络试探。

为了防止cwnd过速增长,需要设置一个慢开始阈值ssthresh状态变量:

  • 当cwnd<ssthresh时,使用慢开始算法。
  • 当cwnd>ssthresh时,改用拥塞避免算法。

这里拥塞避免算法与慢开始算法不同,每经过一个传输轮次RTT发送方的拥塞窗口cwnd增加1,而不是加倍,同时ssthresh的值也加1.无论是在慢开始算法还是在拥塞避免算法阶段,一旦发生拥塞(是否按时收到确认报文),则把ssthresh值设置为拥塞时cwnd值的1/2,然后cwnd设置为1,重新开始慢开始算法。(这是不使用快重传的思路)

快重传和快恢复

在传输过程中,如果发送方在计时器时限已到仍未收到确认,则可能出现了拥塞。对于这种可能出现的拥塞,上面所述情况未使用快重传算法。而对于快重传算法,首先要求接收方在每收到一个失序报文,都会发出重复确认,而不是等自己发数据时候才捎带发送ack。当接收方连续收到3个重复确认,应当立即重传该报文而不必等待计时器时间到。

快重传算法需要和快恢复算法配合使用。在连续收到3个确认报文并重发该报文的同时,为了预防拥塞发生,把慢开始阈值ssthresh减半。此时并不去执行慢开始算法(cwnd=1),而是把cwnd设置为ssthresh减半后的数值,然后执行拥塞避免算法。在采用快恢复的算法时候,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。

我们在谈论上面四种算法的时候,假设接收方拥有足够大的缓存来接收数据。但是实际上接收方缓存有限,所以需要设定一个接收窗口rwnd,在每次向发送方返回确认的时候传送给发送方。这个接收窗口又称为通知窗口,从流量控制的角度发送方的发送窗口不能超过接收方的rwnd值。

综合拥塞控制和流量控制两方面考虑,发送窗口值=min{rwnd,cwnd}。

下一篇文章中将对http协议和HTTPS协议进行总结。

Android网络编程随想录(1)的更多相关文章

  1. Android网络编程随想录(四)

    前面三篇文章从最基础的TCP,HTTP协议理论开始,然后介绍了在Android的开发中所使用的HttpClient和HttpUrlConnection这两种Http客户端.在本文中,我们一起来学习一下 ...

  2. Android网络编程随想录(3)

    大多数Android的app都会使用HTTP协议来发送和接收数据.在Android开发中,通常使用两种http客户端:一个是Apache的HttpClient,另一个是HttpURLConnectio ...

  3. Android网络编程随想录(2)

    上篇文章介绍了传输层TCP协议的理论知识,本文主要介绍了TCP协议基础之上HTTP协议和HTTPS协议的理论知识. HTTP协议基于TCP协议定义了客户端向服务器请求数据的方式,它是面向事务的应用层协 ...

  4. Android网络编程只局域网传输文件

    Android网络编程之局域网传输文件: 首先创建一个socket管理类,该类是传输文件的核心类,主要用来发送文件和接收文件 具体代码如下: package com.jiao.filesend; im ...

  5. Android网络编程基础

    Android网络编程只TCP通信 TCP 服务器端工作的主要步骤如下.步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上.步骤2 调用acc ...

  6. Android网络编程系列 一 TCP/IP协议族

    在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必 ...

  7. Android网络编程系列 一 Socket抽象层

     在<Android网络编程>系列文章中,前面已经将Java的通信底层大致的描述了,在我们了解了TCP/IP通信族架构及其原理,接下来我们就开始来了解基于tcp/ip协议层的Socket抽 ...

  8. Android 网络编程 Socket

    1.服务端开发 创建一个Java程序 public class MyServer { // 定义保存所有的Socket,与客户端建立连接得到一个Socket public static List< ...

  9. Android网络编程概述

    Android网络编程概述 首先,应该了解的几个问题: 1)Android平台网络相关API接口 a) java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流.数据包 ...

随机推荐

  1. (转)基于Metronic的Bootstrap开发框架经验总结(3)--下拉列表Select2插件的使用

    http://www.cnblogs.com/wuhuacong/p/4761637.html 在上篇<基于Metronic的Bootstrap开发框架经验总结(2)--列表分页处理和插件JST ...

  2. TextInputLayout使用时各个地方的字体颜色

    我们现在在做Android端的输入框时,要具备如下功能: 默认提示获取焦点时提示上移至输入框顶部获取焦点时输入框有提示错误时增加错误提示直接上图: 默认情况: 获取焦点时: 开始输入文字时: 有错误时 ...

  3. 【转载】使用JSONObject生成和解析json

    1. json数据类型 类型 描述 Number 数字型 String 字符串型 Boolean 布尔型 Array 数组 Object 对象 null 空值 (1)json中不区分整数.小数等类型, ...

  4. namespace、struct、enum、union、string(day01)

    一 C++概述 C++历史背景 )C++的江湖地位 jave C C++ C# python )C++之父:Bjarne Stroustrup(--) ,Cpre,为C语言增加类的机制 ,Bjarne ...

  5. [luogu4251 SCOI2015] 小凸玩矩阵 (二分图最大匹配)

    传送门 Description Input Output 输出包含一行,为选出的 n 个数中第 k 大数的最小值. Sample Input 输入样例1: 2 3 1 1 2 4 2 4 1 输入样例 ...

  6. PHP多进程初探 --- 利用多进程开发点儿东西吧

    [原文地址:https://blog.ti-node.com/blog...] 干巴巴地叨逼叨了这么久,时候表演真正的技术了! 做个高端点儿的玩意吧,加入我们要做一个任务系统,这个系统可以在后台帮我们 ...

  7. (37)Spring Boot集成EHCache实现缓存机制【从零开始学Spring Boot】

    [本文章是否对你有用以及是否有好的建议,请留言] 写后感:博主写这么一系列文章也不容易啊,请评论支持下. 如果看过我之前(35)的文章这一篇的文章就会很简单,没有什么挑战性了. 那么我们先说说这一篇文 ...

  8. (4)Spring Boot使用别的json解析框架【从零开始学Spring Boot】

    此文章已经废弃,请看新版的博客的完美解决方案: 78. Spring Boot完美使用FastJson解析JSON数据[从零开始学Spring Boot] http://412887952-qq-co ...

  9. Efficient ticket lock synchronization implementation using early wakeup in the presence of oversubscription

    A turn-oriented thread and/or process synchronization facility obtains a ticket value from a monoton ...

  10. 0120Keeplived实现自动切换Mysql服务

    转自http://biancheng.dnbcw.info/mysql/381020.html Keepalived+mysql 自动切换网络结构:VIP 192.168.88.200mysq11 1 ...