像上面这样的拥塞窗口增长速度
,
是指数级别的
. "
慢启动
"
只是指初使时慢
,
但是增长速度非常快
.
为了不增长的那么快
,
因此不能使拥塞窗口单纯的加倍
.
此处引入一个叫做慢启动的阈值
当拥塞窗口超过这个阈值的时候
,
不再按照指数方式增长
,
而是按照线性方式增长。
2.8 延迟应答
如果接收数据的主机立刻返回
ACK
应答
,
这时候返回的窗口可能比较小
.
假设接收端缓冲区为
1M.
一次收到了
500K
的数据
;
如果立刻应答
,
返回的窗口就是
500K;
但实际上可能处理端处理的速度很快
, 10ms
之内就把
500K
数据从缓冲区消费掉了
;
在这种情况下
,
接收端处理还远没有达到自己的极限
,
即使窗口再放大一些
,
也能处理过来
;
如果接收端稍微等一会再应答
,
比如等待
200ms
再应答
,
那么这个时候返回的窗口大小就是
1M;
一定要记得
,
窗口越大
,
网络吞吐量就越大
,
传输效率就越高
.
我们的目标是在保证网络不拥塞的情况下尽量提高传输效
率
;
那么所有的包都可以延迟应答么
?
肯定也不是
;
数量限制
:
每隔
N
个包就应答一次
;
时间限制
:
超过最大延迟时间就应答一次
;
具体的数量和超时时间
,
依操作系统不同也有差异
;
一般
N
取
2,
超时时间取
200ms。
2.9 捎带应答
在延迟应答的基础上
,
我们发现
,
很多情况下
,
客户端服务器在应用层也是
"
一发一收
"
的
.
意味着客户端给服务器说了
"How are you",
服务器也会给客户端回一个
"Fine, thank you";
那么这个时候
ACK
就可以搭顺风车
,
和服务器回应的
"Fine, thank you"
一起回给客户端。
2.10 面向字节流
创建一个
TCP
的
socket,
同时在内核中创建一个
发送缓冲区
和一个
接收缓冲区
;
调用
write
时
,
数据会先写入发送缓冲区中
;
如果发送的字节数太长
,
会被拆分成多个
TCP
的数据包发出
;
如果发送的字节数太短
,
就会先在缓冲区里等待
,
等到缓冲区长度差不多了
,
或者其他合适的时机发送出去
;
接收数据的时候
,
数据也是从网卡驱动程序到达内核的接收缓冲区
;
然后应用程序可以调用
read
从接收缓冲区拿数据
;
另一方面
, TCP
的一个连接
,
既有发送缓冲区
,
也有接收缓冲区
,
那么对于这一个连接
,
既可以读数据
,
也可以
写数据
.
这个概念叫做
全双工
由于缓冲区的存在
, TCP
程序的读和写不需要一一匹配
,
例如
:
写
100
个字节数据时
,
可以调用一次
write
写
100
个字节
,
也可以调用
100
次
write,
每次写一个字节
;
读
100
个字节数据时
,
也完全不需要考虑写的时候是怎么写的
,
既可以一次
read 100
个字节
,
也可以一次
read
一个字节
,
重复
100
次
;
三:TCP和UDP对比
我们说了
TCP
是可靠连接
,
那么是不是
TCP
一定就优于
UDP
呢
? TCP
和
UDP
之间的优点和缺点
,
不能简单
,
绝对的进行比
较
TCP
用于可靠传输的情况
,
应用于文件传输
,
重要状态更新等场景
;
UDP
用于对高速传输和实时性要求较高的通信领域
,
例如
,
早期的
QQ,
视频传输等
.
另外
UDP
可以用于广播
;
归根结底
, TCP
和
UDP
都是程序员的工具
,
什么时机用
,
具体怎么用
,
还是要根据具体的需求场景去判定
.
四:网络层
4.1 ip协议
![四步帮你弄明白网络编程之第三步_第14张图片](http://img.e-com-net.com/image/info8/607b70a71efb49a2a5a6c2cf04214882.jpg)
基本概念
主机
:
配有
IP
地址
,
但是不进行路由控制的设备
;
路由器
:
即配有
IP
地址
,
又能进行路由控制
;
节点
:
主机和路由器的统称
;
4
位版本号
(version):
指定
IP
协议的版本
,
对于
IPv4
来说
,
就是
4.
4
位头部长度
(header length): IP
头部的长度是多少个
32bit,
也就是
length * 4
的字节数
. 4bit
表示最大的
数字是
15,
因此
IP
头部最大长度是
60
字节
.
8
位服务类型
(Type Of Service): 3
位优先权字段
(
已经弃用
), 4
位
TOS
字段
,
和
1
位保留字段
(
必须置为
0). 4
位
TOS
分别表示
:
最小延时
,
最大吞吐量
,
最高可靠性
,
最小成本
.
这四者相互冲突
,
只能选择一个
.
对于
ssh/telnet
这样的应用程序
,
最小延时比较重要
;
对于
ftp
这样的程序
,
最大吞吐量比较重要
.
16
位总长度
(total length): IP
数据报整体占多少个字节
.
16
位标识
(id):
唯一的标识主机发送的报文
.
如果
IP
报文在数据链路层被分片了
,
那么每一个片里面的这个
id
都是相同的
.
3
位标志字段
:
第一位保留
(
保留的意思是现在不用
,
但是还没想好说不定以后要用到
).
第二位置为
1
表示禁
止分片
,
这时候如果报文长度超过
MTU, IP
模块就会丢弃报文
.
第三位表示
"
更多分片
",
如果分片了的话
,
最
后一个分片置为
1,
其他是
0.
类似于一个结束标记
.
13
位分片偏移
(framegament offffset):
是分片相对于原始
IP
报文开始处的偏移
.
其实就是在表示当前分片在
原报文中处在哪个位置
.
实际偏移的字节数是这个值
* 8
得到的
.
因此
,
除了最后一个报文之外
,
其他报文的
长度必须是
8
的整数倍
(
否则报文就不连续了
).
8
位生存时间
(Time To Live, TTL):
数据报到达目的地的最大报文跳数
.
一般是
64.
每次经过一个路由
, TTL -=
1,
一直减到
0
还没到达
,
那么就丢弃了
.
这个字段主要是用来防止出现路由循环
8
位协议
:
表示上层协议的类型
16
位头部校验和
:
使用
CRC
进行校验
,
来鉴别头部是否损坏
.
32
位源地址和
32
位目标地址
:
表示发送端和接收端
.
选项字段
(
不定长
,
最多
40
字节
):
4.2 网段划分
IP
地址分为两个部分
,
网络号和主机号
网络号
:
保证相互连接的两个网段具有不同的标识
;
主机号
:
同一网段内
,
主机之间具有相同的网络号
,
但是必须有不同的主机号
;
不同的子网其实就是把网络号相同的主机放到一起
.
如果在子网中新增一台主机
,
则这台主机的网络号和这个子网的网络号一致
,
但是主机号必须不能和子网中
的其他主机重复
.
通过合理设置主机号和网络号
,
就可以保证在相互连接的网络中
,
每台主机的
IP
地址都不相同
.
那么问题来了
,
手动管理子网内的
IP,
是一个相当麻烦的事情
.
有一种技术叫做
DHCP,
能够自动的给子网内新增主机节点分配
IP
地址
,
避免了手动管理
IP
的不便
.
一般的路由器都带有
DHCP
功能
.
因此路由器也可以看做一个
DHCP
服务器
.
过去曾经提出一种划分网络号和主机号的方案
,
把所有
IP
地址分为五类
,
如下图所示
(
该图出 自
[TCPIP])
。
A
类
0.0.0.0
到
127.255.255.255
B
类
128.0.0.0
到
191.255.255.255
C
类
192.0.0.0
到
223.255.255.255
D
类
224.0.0.0
到
239.255.255.255
E
类
240.0.0.0
到
247.255.255.255
随着
Internet
的飞速发展
,
这种划分方案的局限性很快显现出来
,
大多数组织都申请
B
类网络地址
,
导致
B
类地址很快就分
配完了
,
而
A
类却浪费了大量地址
;
例如
,
申请了一个
B
类地址
,
理论上一个子网内能允许
6
万
5
千多个主机
. A
类地址的子网内的主机数更多
.
然而实际网络架设中
,
不会存在一个子网内有这么多的情况
.
因此大量的
IP
地址都被浪费掉了
.
针对这种情况提出了新的划分方案
,
称为
CIDR(Classless Interdomain Routing):
引入一个额外的子网掩码
(subnet mask)
来区分网络号和主机号
;
子网掩码也是一个
32
位的正整数
.
通常用一串
"0"
来结尾
;
将
IP
地址和子网掩码进行
"
按位与
"
操作
,
得到的结果就是网络号
;
网络号和主机号的划分与这个
IP
地址是
A
类、
B
类还是
C
类无关
;
总结
这段时间考试给我丫的喘不过气来,感觉电子信息太卷了,不知道大家是不是这样呢?忙完第一时间来维护我的博客,编程真的是熟能生巧,一段时间不咋敲代码,感觉啥也不会了,码文不易。大家多多互动,感激不尽!