加油!偷博人!
0、killer application(杀手级应用)
1.网络流量占比大
2.最能吸引用户
比如,Video Application:youtube,tiktok,iqiyi,Tencent movie…
视频流量:占据着互联网大部分的带宽
挑战:异构性
不同用户拥有不同的能力(例如:有线接入和移动用户;带宽丰富和受限用户)
解决方案: 分布式的,应用层面的基础设施
再来口水话谈谈视频:
- 视频:固定速度显示的图像序列。 e.g. 24 images/sec
-
网络视频特点:
高码率:>10x于音频,高的网络带宽需求
可以被压缩
90%以上的网络流量是视频
-
数字化图像:像素的阵列
每个像素被若干bits表示
-
编码:使用图像内和图像间的冗余来降低编码的比特数
空间冗余(图像内)
时间冗余(相邻的图像间)
例子如下
frame帧Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结 Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
0.1存储视频的流化服务 (边下边看)
多媒体流化服务:DASH
- DASH: Dynamic, Adaptive Streaming over HTTP(在http之上的动态自适应的流化技术)
-
服务器:
将视频文件分割成多个块
每个块独立存储,编码于不同码率(8-10种)
告示文件(manifest file): 提供不同块的URL
-
客户端:
先获取告示文件
周期性地测量服务器到客户端的带宽
查询告示文件,在一个时刻请求一个块,HTTP头部指定字节范围
如果带宽足够,选择最大码率的视频块
会话中的不同时刻,可以切换请求不同的编码块 (取决于当时的可用带宽)
-
“智能”客户端: 客户端自适应决定
什么时候去请求块 (不至于缓存挨饿,或者溢出)
请求什么编码速率的视频块 (当带宽够用时,请求高质量的视频块)
哪里去请求块 (可以向离自己近的服务器发送URL,或者向高可用带宽的服务器请求)
理解的太粗糙了,还不太懂Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
一、CDN (Content Distribution Networks)
挑战: 服务器如何通过网络向上百万用户同时流化视频内容 (上百万视频内容)?
-
选择1: 单个的、大的超级服务中心“megaserver”
服务器到客户端路径上跳数较多,瓶颈链路的带宽小导致停顿
“二八规律”决定了网络同时充斥着同一个视频的多个拷贝,效率低(付费高、带宽浪费、效果差)
单点故障点,性能瓶颈
周边网络的拥塞
评述:相当简单,但是这个方法不可扩展
- 选项2: 通过CDN,全网部署缓存节点,存储服务内容,就近为用户提供服务,提高用户体验
-
enter deep: (一种部署策略“深入群众”)
将CDN服务器深入到许多接入网
更接近用户,数量多,离用户近,管理困难
Akamai, 1700个位置
-
bring home: (又一种部署策略“抢注关键”)
部署在少数(10个左右)关键位置,如将服务器簇安装于POP附近(离若干1stISP POP较近)
采用租用线路将服务器簇连接起来
Limelight
-
中国蓝汛,CDN服务提供商。做内容加速服务 (流媒体点播、实时多媒体,直播、春晚的直播)![]()
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
1.举个例子:
Netflix (译为奈飞或网飞,是一家会员订阅制的流媒体播放平台)买了Akamai的内容加速服务,对影视MadMen预先部署在缓存节点中(下图边缘的黑褐色节点)的。
- 当用户点播MadMen,(左边的小房子Where’s MadMen?)
- 然后就会拿到一个告示文件manifest file。
- 在告示文件中,就可以知道有哪些部署的节点可以点播。
- 于是优先选择最近的、网络拥塞最轻微的、流量较少的、即最优的一个节点,点播视频(红色箭头)
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
在应用层、网络边缘来提供网络加速服务。
2.CDN:“简单”内容访问场景——一个简单例子看看CDN的运行
这个图很乱,我来解释一下:
①:Bob浏览netcema.com的网页,找到一个自己喜欢的小电影(url是http://netcinema.com/6y7b23v ,当然这个url我没试过是不是真的 )并且鼠标点击了。
②这个url去到local name server 名字解析服务器代理
③然后local name server找到一级一级找到netcinema的权威名字服务器。权威名字服务器返回一个重定向的一条url “http://kKingCDN.com…”告诉local name server “你要再去解析这个url”
④然后local name server去赵KingCDN的权威名字服务器,得到了离Bob(客户)the closest 一个cache节点。
⑤于是Bob(客户端)就从local name server中知道了离自己最近的缓存节点。
⑥Bob 就向这个最近的缓存节点请求dash的流化服务,可以在网页看小电影了
现在自己在看一张图
一、TCP套接字编程
1.Socket编程
-
应用进程使用传输层提供的服务才能够交换报文,实现应用协议,实现应用
TCP/IP:应用进程使用Socket API访问传输服务
地点:界面上的SAP(Socket) 方式:Socket API
- 目标: 学习如何构建能借助sockets进行通信的C/S应用程序socket: 分布式应用进程之间的门,传输层协议提供的端到端 服务接口
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
2种传输层服务的socket类型:
3. TCP: 可靠的、字节流的服务
4. UDP: 不可靠(数据UDP数据报)服务
2.TCP套接字
套接字: 应用进程与端到端传输协议(TCP或UDP)之间的门户
TCP服务: 从一个进程向另一个进程可靠地传输字节流
3.TCP套接字编程
服务器首先运行,等待连接建立
-
1:服务器进程必须先处于运行状态
创建欢迎socket (创建一个socket返回一个整数,还无意义)
(再将这个整数)和本地端口捆绑
在欢迎socket上阻塞式等待接收用户的连接 (如果无人连接,则阻塞着)
(创建捆绑等待 ,这些都是socket api函数)
客户端主动和服务器建立连接:
-
2:创建客户端本地套接字(隐式捆绑到本地port)
指定服务器进程的IP地址和端口号,与服务器进程连接
-
3 :当与客户端连接请求到来时
服务器接受来自用户端的请求,解除阻塞式等待,返回一个新的socket,(connection socket值)(与欢迎socket不一样),与客户端通信
允许服务器与多个客户端通信
使用源IP和源端口来区分不同的客户端
- 4:连接API调用有效时,客户端P与服务器建立了TCP连接
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
4.C/S模式的应用样例:
先看两个数据结构,再进一步说明C/S socket 交互: TCP![]()
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结 ![]()
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
下图中Server调用bind函数时,参数&sad 就是上面的sockaddr_in{}的结构体。
在下面一点点的accept()中的 &cad也是sockaddr_in{}这样的结构体
这个图的解释,颇费口舌,先附一下视频链接,看看郑老师的讲解吧,21min19s处开始
大概是这样的:
At first,Server 建立一个WelcomeSocket()返回一个随机的整数(比如说8888)。这个welcomeSocket函数中有一个参数,可以代表,所建立的是一个TCPsocket还是一个UDPsocket,甚至可以是一个IP socket。
这个时候socket表项,如下
socket | s_ip | s_port | c_ip | c_port |
---|---|---|---|---|
8888 | / | / | / | / |
And then,调用 bind()函数,将socket的随机值8888,绑定Server的ip(1.1.1.1)和端口号80.
同时假定,Client的ip为2.2.2.2,端口为777
表项更新如下
s_socket | s_ip | s_port | c_ip | c_port |
---|---|---|---|---|
8888 | 1.1.1.1 | 80 | / | / |
这个表项是应用层和传输层用的一个表项。
and then,Server调用connectionSocket =accept(welcomeSocket, &cad…)再8888这个socket等待,来自用户的建立连接请求,没client请求,就阻塞着…
Now ,it is time for client to establish connection request.
同样,client调用socket(PF_INET,…)得到一个socket随机整数(比如说2222)。
但不一样的是,client不用特意去bind,会有一个隐式的bind。比起服务器,客户端不用指定一个特定的端口去建立socket连接。
现在client也有了一个socket表项.
c_socket | c_ip | c_port | s_ip | s_port |
---|---|---|---|---|
2222 | 2.2.2.2 | 777 | / | / |
表项中其实还有一项,来表示状态(目前是无效状态的)
第六步,client调用connec(),向Server发起连接建立Request。(connect()的一个参数中就指明了Server中的ip:1.1.1.1和port:80的捆绑关系,于是c_socket表项在调用connect()的时候又更新了)
c_socket | c_ip | c_port | s_ip | s_port |
---|---|---|---|---|
2222 | 2.2.2.2 | 777 | 1.1.1.1 | 80 |
这个时候Server socket应答,建立连接,accept()解除阻塞返回一个新的socket整数值(比如8899)
这个时候server的socket 多了一行新的,有表项效值。
s_socket | s_ip | s_port | c_ip | c_port |
---|---|---|---|---|
8888 | 1.1.1.1 | 80 | / | / |
8899 | 1.1.1.1 | 80 | 2.2.2.2 | 777 |
说明一下啊:
这里fork了原来的welcomeSocket,得到新的8899有效socket 新进程,去和client的一个socket进程打交道。
而8888 这个老进程还是守候在80端口,等待新的client进程请求建立连接。
socket的值,代表了一个会话关系!
现在Socket Connection Established,就好办了。开始通过connectionSocket和clientSocket来send、read、write reply。
最后觉得时候离开了,就close
红色箭头代表报文的交互![]()
Day5:应用层——CDN、 TCP 套接字编程、 UDP 套接字编程、小结0、killer application(杀手级应用)一、CDN (Content Distribution Networks)一、TCP套接字编程二、UDP Socket 编程三、小结
下面看一些实现代码
代码解释就更费口舌了,,,还是看看郑老师声情并茂的讲解吧!(37min30s处)
二、UDP Socket 编程
UDP: 在客户端和服务器之间没有连接
- 没有握手
- 发送端在每一个报文中明确地指定目标的IP地址和端口号
- 服务器必须从收到的分组中提取出发送端的IP地址和端口号
UDP: 传送的数据可能乱序,也可能丢失
1.Client/server socket 交互: UDP
看懂了上面TCP的Socket 编程,下面的UDP的Socket编程岂不是易如反掌?(但问题是还不懂上面)