概念
计算机网络 = 通信技术 + 计算机技术 = 通信网络
= 互连
(用交换节点组成的交换网络)的、自治
(无主从关系)的计算机集合
ISP:网络服务提供商
Internet:ISP网络互连的网络之网络
组成部分
计算设备
:主机/端系统 运行分布式应用通信链路
分组交换
:路由器 和 (链路层)交换机协议
网络协议
网络中的数据交换
而进建立的规则、标准或规定。三要素
Internet协议标准 RFC
协议规范了网络中所有信息的接受和发送过程。
网络边缘
主机/端系统
接入网络
指有线或无线通信链路
电话 | 上行 | 下行 | |
---|---|---|---|
带宽 | 0 ~ 4kHz | 4kHz ~ 50kHz | 50kHz ~ 1MHz |
速率 | \ | < 2.5Mbps | < 24Mbps |
典型速率 | \ | < 1Mbps | < 10Mbps |
基站
、“接入点”
)连接端系统或路由器无线局域网LANs | 广域无线接入网 | |
---|---|---|
范围 | 同一建筑物内 (30m) | 通过电信运营商 (蜂窝网) ,接入范围在几十公里 |
类型 | 802.11b/g (WiFi) | 3G、4G: LTE / 移动互联网 |
带宽 | 11 Mbps、 54 Mbps | 1 Mbps、10 Mbps、100 Mbps |
网络核心
互联的路由器网络
关键功能:路由 + 转发 → 数据交换
路由 :从源主机到目的主机的逻辑路径
转发 :从路由器的输入端口到输出端口
ISP网络之网络
IXP:互联网交换中心,各ISP之间数据交换的接口。
一级“商业”ISP:国家或国际范围。
内容提供商网络:私有网络,连接其数据中心和Internet,绕过一级或区域ISP。
区域ISP:连接多个接入ISP。
接入ISP:端系统通过接入ISP(access ISPs )连接到 Internet。
多路复用
链路、网络资源划分成多个“资源片”
过程
方法
TDM、FDM、WDM、CDM
TDM:划分时间帧,周期使用
FDM、WDM:划分频率带宽为模拟信道
CDM:按编码划分
信息整体传输
适用于突发数据传输网络
分组
共同点
二者均采用存储—转发
的交换方式
交换传输时延
假设有n个路由器连接A、B,报文为M bits,速率为R bps,分组交换采取的分组大小为L bits,则:
报文交换的时延:n * M / R
分组交换的时延:M / R + n * L / R
速率
数据率,即 每单位时间传输的bit位数 。单位:bps,kbps,……
带宽
在网络信道中的最高数据率。单位同上
时延
包括四种分组延迟:
传输延迟与传播延迟
传输延迟可看作:收费站闸门打开的时间
传播延迟可看作:车辆在一段高速公路上的所用时间
流量强度
L * a / R
时延带宽积
传播时延 * 带宽 = dprop * R
丢包率
丢包数 / 已发分组总数
吞吐率/量
实体
任何可发送或接收信息的 硬件 或 软件过程
协议
控制两个 对等实体 通信的规则集合
水平的
服务
下层为上层提供服务
下层实现对上层是 透明 、不可见的
垂直的
接口
相邻层 通过 接口 交互
通过 服务访问点 SAP 指定特定服务
由ISO组织提出
—————————————— 以上为 端到端层
数据封装
所有参考模型均使用这一模式
增加控制信息,构造协议数据单元PDU
一切依靠IP,一切为了IP
服务器
客户机
同一主机
操作系统提供通信
不同主机
报文(消息)交换
应用层协议内容
网络应用对传输服务的需求
其中,传输层的TCP/UDP协议均不保证 时间/延迟 和 带宽
由多个对象组成网页
对象寻址
URL:统一资源定位器
host name + port / path name
协议:HTTP 1.0/1.1
默认使用 TCP
服务器端口号:80
体系结构:C/S
无状态
1、连接类型
非持久性连接:每个TCP连接允许传输最多一个对象
HTTP 1.0 默认
持久性连接:每个TCP连接允许传输多个对象
HTTP 1.1 默认
连接类型 | 响应时间 |
---|---|
非持久性连接 | 每个对象需要2个RTT |
持久性无流水连接 | 每个对象需要1个RTT |
持久性流水连接 | 所有对象需要1个RTT |
2、消息格式
使用ASCII编码
请求消息
method | 作用 |
---|---|
POST | 提交表单到服务器 |
GET | 从服务器获取请求对象 |
HEAD | 不将请求对象放入响应消息,可用于测试 |
PUT | 上传至URL指定路径 |
DELETE | 删除URL指定文件 |
CONNECT | 向代理服务器发送代理请求 |
响应消息
格式与请求消息格式基本相同,仅第一行为状态行
version | sp | state |
---|
状态行
state | 含义 |
---|---|
200 OK | 正常响应 |
301 Move Permanently | 对象资源已永久移动 |
302 Move Temporarily | 对象资源暂时移动 |
304 Not Modified | 对象内容没有修改 |
400 Bad Requst | 格式错误 |
404 Not Found | 指定URL不存在对象 |
505 HTTP Version Not Supported | HTTP版本错误 |
需求
功能
在不直接访问服务器的前提下满足HTTP请求
用户设定浏览器通过缓存(代理服务器)进行访问
代理服务器接收客户请求
缓存中有请求对象 —— 直接发送响应消息
缓存中无请求对象 —— 代理服务器向服务器发送HTTP请求
一般由ISP提供
条件性GET方法
组成构件
邮件客户端
读、写Email消息
与服务器交互,收、发Email消息
邮件服务器
邮箱:存储发给某一用户的Email消息
消息队列:存储等待发送的Email消息
协议
特点
消息只使用 7位ASCII码 编码
命令/响应交互模式
命令(command):ASCII文本消息
响应(response):状态代码语句
使用持久性连接
用 CRLF.CRLF 确定结束消息传输
传输过程三阶段
相同点
不同点
对象与响应
· HTTP:每个对象有独立的响应消息
· SMTP:多个对象在由多部分构成的消息中
协议特性
· HTTP:“拉”协议
· SMTP:“推”协议
RFC 822:文本消息格式标准
头部行
消息体
目的
从服务器获取邮件
POP3
无状态
模式
下载并删除:从客户端下载即删除
下载并保持:各客户端均保留拷贝
认证过程
客户端命令
User:声明用户名
Pass:声明密码
服务器响应
+OK
-ERR
事务阶段
IMAP
HTTP
既可作为邮件访问协议,也可作为邮件发送协议。
本地域名服务器
DNS查询方式
name | value | type | ttl |
---|---|---|---|
主机域名 | 主机IP地址 | A | / |
域名 | 对应的权威域名服务器的主机域名 | NS | / |
某一真实域名的别名 | 该真实域名 | CNAME | / |
邮件服务器别名 | 邮件服务器主机域名 | MX | / |
DNS协议
常用于文件分发
原理与文件分发
C/S结构分发时间:max { NF / us , F / mini { di } }
P2P结构分发时间:max { F / us , F / mini { di } , NF / ( us + Σi ui ) }
BitTorrent 协议
Torrent:交换同一个文件的节点组
Tracker:跟踪参与Torrent的节点
文件划分为多个256KB的chunk
节点加入
向tracker注册,获取节点清单,与一些节点(一般邻居数少于10个)建立连接。
下载同时,向其他节点上传chunk。
获取chunk
定期查询“邻居”,稀缺优先
发送chunk(tit for tat)
选择向自己发送chunk速率最大的4个邻居发送(每10s更新)
随机选择一个其他节点发送(每30s更新)
索引
进程级 —— IP地址 + 端口号
集中式索引:所有索引由中央服务器保存
例子:Napster
洪泛式查询:完全分布式,每个节点对它共享的文件进行索引
例子:Gnutella
层次式覆盖网络:一个节点或者是一个超级节点,或者被分配到一个超级节点,并被其跟踪拥有的文件内容
覆盖网络 :由所有 活动节点 和 边(TCP连接) 构成。
本质是P2P —— 索引分布在超级节点上
例子:Skype
Socket API
Socket抽象与地址结构
当应用进程创建套接字时
1. WSAStartup
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
在微软系统中,应用程序在使用Socket之前必须首先调用WSAStartup函数 两个参数
第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本、低位字节指明主版本
十六进制整数,例如0x102表示2.1版
第二个参数返回实际的WinSock的版本信息
指向WSADATA结构的指针
例:使用2.1版本的WinSock的程序代码段
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
2. WSACleanup
int WSACleanup (void);
3. socket
sd = socket( int protofamily, int type, int proto );
创建套接字
sd 为操作系统返回的套接字描述符
protofamily(协议族):protofamily = PF_INET(TCP/IP)
type(套接字类型)
SOCK_STREAM:TCP套接字
SOCK_DGRAM:UDP套接字
SOCK_RAW:直接使用网络层协议的套接字
proto(协议号):默认为0
例:创建一个流(TCP)套接字的代码段
struct protoent *p;
p = getprotobyname("tcp");
SOCKET sd = socket(PF_INET,SOCK_STREAM,p->p_proto);
4. closesocket
int closesocket( SOCKET sd );
关闭一个描述符为sd的套接字
多进程共享一个套接字时,调用一次closesocet,该套接字引用次数减1;减至0时,套接字关闭
多线程共享一个套接字时,引用数仅为1;任何一个线程关闭套接字,其他线程都无法访问该套接字
返回值:
0:成功
SOCKET_ERROR(-1):失败
5. bind
int bind( SOCKET sd, const struct sockaddr * localaddr, int addrlen );
// 初始化bindAddr
SOCKADDR_IN bindAddr;
bindAddr.sin_family = AF_INET;
bindAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindAddr.sin_port = htons(PORT);
if(bind(majorSd, (struct sockaddr *) &bindAddr, sizeof(bindAddr)) ==
-1) // 绑定套接字地址
{
printf("套接字绑定本地地址失败!\n");
return 0;
}
6. listen
int listen( SOCKET sd, int queuesize );
7. accept
SOCKET
accept( SOCKET sd, struct sockaddr *addr, int *addrlen);
通过描述符为sd的套接字向服务器发送请求的客户端被指定与返回的新建套接字建立连接
由使用TCP套接字(面向连接)的服务器调用
addr、addrlen均设为NULL即可
8.connect
int connect( SOCKET sd, struct sockaddr *addr, int addrlen);
struct hostent *host = gethostbyname(header->host); // 查询主机域名的IP地址
if(!host){
printf("查询不到主机 %s 的IP地址\n", header->host);
return;
}
// 目的主机addr
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*)host->h_addr_list[0]));
serverAddr.sin_port = htons(HTTP_PORT);
if (connect(proxySocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) // 连接失败
{
printf("无法连接主机 %s\n", header->host);
return;
}
9. send / sendto
int send( SOCKET sd, const char *buf, int buflen, int flag);
TCP服务器与客户端通信间发送数据使用
使用了connect函数的UDP客户端发送数据使用
int sendto( SOCKET sd, const char *buf, int buflen, int flag, const struct sockaddr *destaddr, int addrlen);
UDP服务器发送数据使用
未使用connect函数的UDP客户端发送数据使用
10. recv /recvfrom
int recv( SOCKET sd, const char *buf, int buflen, int flag);
TCP服务器与客户端通信间接收数据使用
服务器从使用了connect函数的UDP客户端接收数据使用
int recvfrom( SOCKET sd, const char *buf, int buflen, int flag, const struct sockaddr *senderaddr, int addrlen);
从UDP服务器接收数据使用
从未使用connect函数的UDP客户端接收数据使用
11. setsockopt / getsockopt
int setsockopt( int sockfd, int level, int optname, const void *optval, socklen_t optlen );
int getsockopt( int sockfd, int level, int optname, void *optval, socklen_t *optlen );
12. gethostbyname
struct hostent *gethostbyname( const char *name );
struct hostent{
char *h_name; // 正式主机名
char ** h_aliases; // 主机别名
short h_addrtype; // 主机IP地址类型:IPV4-AF_INET
short h_length; // 主机IP地址字节长度,IPv4为32位
char ** h_addr_list; // 主机的IP地址列表(字符串形式)
};
127.0.0.1
13. inet_addr / inet_nota
点分十进制字符串
转换为网络字节的IP地址
32位网络字节IP地址
转换为点分十进制字符串
14. htonl / htons
特点
应用进程间的逻辑通信
服务
协议
UDP
Best-Effort
TCP
拥塞控制
流量控制
连接建立
本质
将主机—主机间的交付拓展到进程—进程间的交付。
应用场景
标识
UDP Socket 标识:二元组 (目的IP地址,目的端口号)
TCP Socket 标识:四元组 (源IP地址,源端口号,目的IP地址,目的端口号)
四元组可有效区分多线程Socket
Socket不一定与进程一 一对应
周知端口号
1 ~ 1023
服务器可使用bind绑定周知端口号
基于Internet IP协议
复用/分用
简单的错误校验
“Best effort”服务
无连接
发送方与接收方之间不需要握手
每个UDP段的处理互相独立
常用于流媒体
容忍丢失
速率敏感
实现可靠数据传输
在应用层增加可靠性机制和错误恢复机制,可实现基于UDP的可靠数据传输
计算范围
伪首部 + UDP首部 + 报文(消息)
伪首部
计算方法
将每16位视为一个整型数,求和,进位加在最低位
,对最终结果按位取反
。
可靠
无错误
无丢失
无乱序
设计思路
由简到繁渐进地设计发送方与接收方的协议
只考虑单向传输,实际为双向流动
利用有限状态机(FSM)来刻画传输协议
假设前提
底层信道完全可靠
无错误
无丢失
发送方与接收方的FSM互相独立
假设前提
底层信道可能产生位错误。
新机制
差错检测
校验和
恢复机制
确认机制ACK
重传机制
采用确认重传机制的协议被称为ARQ(自动重传请求)协议。
发送方与接收方的FSM
停—等协议:仅当收到ACK才回到发送状态
假设前提
底层信道可能产生位错误。
ACK/NAK也可能有错误。
新机制
ACK/NAK重传机制
产生重复分组
重复分组处理
发送方:使用序列号
接收方:丢弃重复分组
发送方与接收方的FSM
发送方
假设前提
底层信道可能产生位错误。
不使用NAK。
ACK可能有错误。
新机制
新确认机制
ACK显式加入序列号
ACK告知最后一个正确接收的分组
新重传机制
收到重复的ACK即重传
假设前提
底层信道可能产生位错误或分组丢失。
仅使用ACK,且ACK也可能有错误。
新机制
新重传机制
发送方超时重传机制
发送方与接收方的FSM
任何协议都不能完美地实现可靠。这取决于实际环境。
信道利用率
( Wsend * L / R ) / T
实现信道利用率最大,即信道利用率 ≥ 1。
rdt 3.0 信道利用率
忽略ACK大小,信道利用率为:
( L / R ) / ( RTT + L / R ) ≈ 0.00027
由于停等性质,利用率很低。
流水线
通过流水线机制使得信道利用率提高
实现
窗口
允许使用的序列号范围
窗口尺寸为N:最多有N个等待确认的消息
滑动窗口
随着协议的运行,窗口在序列号空间内向前滑动
滑动窗口协议
GBN
SR
发送方
ACK机制
发送已正确接收的序号最大分组的ACK
即累计确认
乱序处理
乱序到达的分组直接丢弃
重新发送最后确认分组的ACK
( Wsend * L / R ) / T
= ( Wsend * L / R ) / ( RTT + L / R )
= ( Wsend * L / R ) / ( 2 * dprop + L / R )
窗口尺寸
若使信道利用率最大,则
( Wsend * L / R ) / ( 2 * dprop + L / R ) ≥ 1
Wsend ≥ ( 2 * dprop * R + L ) / L
序号位数
≥ *log2 ( Wsend + 1 )
特点
缓存不必要重传的分组,为每个分组设置计时器。
接收方/发送方窗口
收到数据来自上层
如果序号在发送窗口内 → 发送该分组
超时
重传其超时分组
收到ACK
序号在窗口内 → 标记为已接收ACK
如果序号等于send_base → 向前滑动至未接收确认ACK的分组
接收方
接收到分组
接收分组序号在[rcv_base, rcv_base + N - 1]内
没收到过的分组 → 缓存
序号等于rcv_base → 将所有收到的分组按序向上交付,直到有没收到的按序分组,窗口向前滑动
接收分组序号在[rcv_base - N, rcv_base - 1]内
发送对应的ACK
这是必要的,否则发送方窗口可能因未收到对应的ACK,而无法向前滑动,无法同步。
其他情况
忽略
所有可靠数据传输协议满足:
Wsend + Wrecv ≤ 2 k
实际应用中通过假定某序号x的最大存活时间保证该序号可重新使用。
TCP的存活时间设置为3min。
1、特点
点对点
一个发送端(进程),一个接收端(进程)
可靠、按序的字节流
机制
流水线机制
拥塞机制 → 网络
流量控制 → 接收方
发送/接收方具有缓存
全双工
同一连接中能够传输双向数据流
面向连接
通信双方发送数据前必须建立连接
只在通信方两端维护连接状态
在IP协议提供的不可靠服务基础上实现可靠数据传输服务
序号
该报文段的首字节在字节流中的编号。
TCP建立连接时,双方随机选择序号开始(相对序号为0)。
ACK确认号
希望收到的下一字节的序号。
累计确认,乱序到达分组的处理由实现者决定(通常将其缓存)。
标志段
选项字段
协商MSS(最大报文长度,单位为B)
MSS = MTU(最大链路层帧长) - IP首部长度 - TCP首部长度
时间戳等
流水线机制
TCP使用单一重传计时器
累计确认
触发重传的事件
超时
重复ACK
超时
超时时间 = EstimatedRTT + 4 * DevRTT
EstimatedRTT = (1 - α) * EstimatedRTT + α * SampleRTT
DevRTT = (1-β) * DevRTT + β * |SampleRTT - EstimatedRTT |
经典值
α = 0.125
β = 0.25
初始超时时间为 1s
发送方事件与响应
开始发送数据
开启计时器
设置初始超时时间
nextseqnum += len(data)
超时
重传引起超时的段
重启计时器
收到ACK
如果ACK序号n > send_base
事件 | 接收方动作 |
---|---|
期望序号报文段到达,且之前的均已确认 | 延迟ACK,最多等待500ms,如果下一个按序报文段未到达,发送对应ACK |
期望序号报文段到达,另一按序报文段在等待ACK | 立即发送该ACK,确认二者均到达 |
间隔中的报文段到达 | 若该报文段位于间隔中序号小的一端,立即发送ACK |
比期望序号大的报文段到达 | 立即发送冗余ACK |
快速重传机制
前提
计时器每发生超时,超时时间将加倍,因此确认超时的开销将变大。
发生条件
收到 3个冗余ACK
具体动作
// 伪代码
收到ACK,确认号为y;
if y > send_base :
send_base = y;
if 存在未确认的已发送报文段 :
启动计时器;
else :
y的冗余ACK数 + 1;
if y的冗余ACK数为3 :
重传具有序号y的报文段;
接收窗口
TCP连接为全双工,发送方与接收方均有缓存。
窗口大小
RevBuffer ≥ RevWindow = LastByteRcvd - LastByteRead
RevWindow:接收窗口中的可用空间
LastByteRcvd:已缓存的最后一个字节
LastByteRead:已读入上层的最后一个字节
如果此时RevWindow等于0,发送方继续发送1B的报文段。
连接建立
三次握手
SYN段
、SYNACK段
占1字节,双方发送序号相对从1开始,实际上是随机选择从某个序号开始。
当第三次握手结束后,发送方立刻发送PSH段
,即通知接收方开始接收数据,并开始使用流水线机制。
拥塞表现
分组丢失
分组延迟过大
拥塞原理分析
· 场景1
仅有一个路由器,但它具有无限缓存
场景1可知拥塞时分组延迟大。
· 场景2
有多个路由器,但存在超时/重传事件
场景2和场景3需要更多的重传,造成资源浪费。
拥塞控制方法
TCP采用端到端拥塞控制
端系统通过观察判断
网络辅助拥塞控制
路由器显式地反馈
网络辅助拥塞控制实例:ATM ABR
ABR — available bit rate
“弹性服务”
网络正常时,使用可用带宽
网络拥塞(overloaded)时,将发送速率降低到最低保障速率
RM cells — resource management cells
从发送方发送,由路径上的交换机进行网络辅助
交换机设置RM cell
位:NI
表示速率不许增长,CI
指示拥塞
最后由接收方返回给发送方
RM cell
有显式的速率ER
字段:两个字节
拥塞的交换机可以降低ER
值
发送方通过ER
值获知路径支持的最小速率
data cell
具有EFCI
位:拥塞的交换机将其设为1
如果RM cell
前面的data cell
的EFCI
位被设为1,接收方将在返回的RM cell
中置CI
位
TCP 拥塞控制原理
rate ≈ cwin / RTT B/sec
cwin = min{ 拥塞窗口,接收窗口 } = 发送窗口 ≥ LastByteSent - LastByteAcked
cwin 是一个反映网络拥塞程度的值
感知网络拥塞
loss事件 = 超时或3个冗余ACK
调整发送速率
AIMD 、SS
慢启动 SS
加性增乘性减 AIMD
该处理方式属于TCP Tahoe版本,Tahoe版本和Reno版本对比图如下。
平均吞吐率
0.75 Maxcwin / RTT
Maxcwin为cwin在发生loss事件时的值。
公平性
虚电路网络
连接服务
为系列分组确定路径
过程:连接建立
实现方式:路由
沿该路径传输分组
传输结束拆除连接
典型:ATM
ATM 服务种类 | 特点 |
---|---|
CBR | 电路仿真(速率不变) |
VBR | 速率可变 |
ABR | 速率可用(具有最低保障) |
UBR | 速率不定 |
数据报网络
虚电路(VC)
一条从源主机到目的主机,类似于电路的路径(逻辑连接)
特点
主机-主机的连接由网络核心实现。
通信过程
实现
每个分组携带虚电路标识VCID
网络设备维护每条经过它的虚电路的连接状态
链路、网络设备资源面向虚电路进行预分配
每条虚电路包括:
从源主机到目的主机的一条路径
虚电路标识,每段链路一个编号
沿路每个网络设备,利用转发表记录经过的虚电路
转发分组时,依据转发表改写/替换VCID
VC转发表格式
输入接口 | 输入VCID | 输出接口 | 输出VCID |
---|---|---|---|
1 | 12 | 3 | 22 |
虚电路信令协议
特点
数据报转发表