五指山网站开发价格,免费申请网站域名,网站模板下载,手机网站定制文章目录 零、前言一、应用层协议原理1.1 网络应用的体系结构1.1.1 客户-服务器(C/S)体系结构1.1.2 对等体#xff08;P2P#xff09;体系结构1.1.3 C/S 和 P2P体系结构的混合体 1.2 进程通信1.2.1 问题1#xff1a;对进程进行编址#xff08;addressing#xff09;#… 文章目录 零、前言一、应用层协议原理1.1 网络应用的体系结构1.1.1 客户-服务器(C/S)体系结构1.1.2 对等体P2P体系结构1.1.3 C/S 和 P2P体系结构的混合体 1.2 进程通信1.2.1 问题1对进程进行编址addressing服务用户1.2.2 问题2传输层提供的服务1.2.2.1 需要穿过层间的信息1.2.2.2 层间信息的代表1.2.2.3 TCP 之上的套接字socket1.2.2.4 UDP socket1.2.2.5 UDP之上的套接字socket1.2.2.6 套接字socket 1.2.3 如何使用传输层提供的服务实现应用 1.3 应用层协议1.3.1 应用需要传输层提供什么样的服务?如何描述传输层的服务?1.3.2 Internet 传输层提供的服务1.3.3 UDP 存在的必要性1.3.4 Internet应用及其应用层协议和传输协议1.3.5 安全TCP 二、Web 和 HTTP2.1 HTTP概况2.2 HTTP 连接2.2.1 非持久HTTP连接2.2.2 响应时间模型2.2.3 持久HTTP 2.3 HTTP 请求报文2.3.1 通用格式2.3.2 提交表单输入2.3.3 方法类型 2.4 HTTP响应报文2.4.1 HTTP 响应状态码2.4.2 Trying out HTTP (client side) for yourself 2.5 用户-服务器状态cookies2.6 Web 缓存代理服务器2.6.1 条件GET方法 三、FTP3.1 FTP: 控制连接与数据连接分开3.2 FTP 命令, 响应 四、Email4.1 Email邮件服务器4.2 EmailSMTP[RFC 2821]4.3 简单的SMTP交互4.4 SMTP 总结4.5 邮件报文格式4.6 报文格式多媒体扩展4.7 邮件访问协议4.7.1 POP3协议4.7.2 POP3 与 IMAP协议 五、DNS5.1 DNS 的必要性5.2 DNS(domain name system) 系统需要解决的问题5.3 DNS 的历史5.4 DNS(Domain Name system)总体思路和目标5.5 问题1DNS名字空间The DNS Name Space5.5.1 DNS: 根名字服务器5.5.2 DNS 名字空间 5.6 问题2解析问题——名字服务器Name Server5.6.1 名字空间划分为若干区域Zone5.6.2 TLD 服务器5.6.3 区域名字服务器维护资源记录5.6.4 DNS(Domain Name System)5.6.5 本地名字服务器Local Name Server5.6.6 ★递归查询5.6.7 迭代查询5.6.8 DNS 协议、报文5.6.9 提高性能缓存 5.7 问题3维护问题新增一个域5.7.1 攻击DNS 六、P2P应用6.1 纯P2P架构6.2 文件分发C/S vs P2P6.2.1 文件分发时间C/S模式6.2.2 文件分发时间P2P模式6.2.3 Client-server vs. P2P6.2.4 P2P文件共享6.2.5 非结构化P2P6.2.5.1 P2P集中式目录6.2.5.2 查询洪泛Gnutella完全分布式6.2.5.3 利用不匀称性KaZaA混合体6.2.5.4 P2P文件分发BitTorrent 6.2.6 DHT(结构化P2P) 七、CDN7.1 视频流化服务和CDN上下文7.2 多媒体视频7.3 存储视频的流化服务7.3.1 多媒体流化服务DASH7.3.2 流式多媒体技术3DASH 7.4 内容分发网Content Distribution Networks 八、TCP/IP Socket编程快速入门8.1 创建简单服务器8.2 客户端8.3 并发多客户端通信8.3.1 多线程的Socket 服务器 8.4 简易HTTP服务器 九、TCP 套接字编程9.1 Socket 编程9.2 TCP套接字编程9.3 数据结构 sockaddr_in9.4 数据结构 hostent9.5 例子C客户端(TCP)9.6 例子C服务器(TCP) 十、UDP 套接字编程10.1 Client/server socket 交互UDP10.2 样例C客户端UDP1.3 样例C服务器(UDP) 零、前言 网络应用是计算机网络存在的理由。 如果我们不能构想出任何有用的应用 也就没有必要去设计支持它们的网络协议了。 目标:
网络应用的原理网络应用协议的概念和实现方面 传输层的服务模型客户-服务器模式对等模式peer-to-peer内容分发网络 网络应用的实例互联网流行的应用层协议 HTTPFTPSMTP / POP3 / IMAP / DNS 编程网络应用协议 socket API
创建一个新的网络应用 编程 在不同的端系统上运行通过网络基础设施提供的服务应用进程彼此通信如Web Web 服务器软件与浏览器软件通信 网络核心中没有应用层软件 网络核心中没有应用层功能网络应用只在端系统上存在快速网络应用开发和部署 一、应用层协议原理
1.1 网络应用的体系结构
可能的应用架构
客户-服务器模式(C/S : client / server)对等模式(P2P: Peer To Peer)混合体
1.1.1 客户-服务器(C/S)体系结构 服务器 一直运行固定的 IP 地址和周知的端口号约定扩展性服务器场 数据中心进行扩展扩展性差 客户端 主动与服务器通信与互联网有间歇性的连接可能是动态IP地址不直接与其它客户端通信
1.1.2 对等体P2P体系结构 几乎没有一直运行的服务器任意端系统之间可以进行通信每一个节点既是客户端又是服务器 自扩展性-新peer 节点带来新的服务能力当然也带来了新的服务请求 参与的主机间歇性连接且可以改变IP地址 难以管理 例子Gnutella迅雷
1.1.3 C/S 和 P2P体系结构的混合体
Napster
文件搜索集中 主机在中心服务器上注册其资源主机向中心服务器查询资源位置 文件传输P2P 任意Peer节点之间
即时通信
在线检测集中 当用户上线时向中心服务器注册其IP地址用户与中心服务器联系以找到其在线好友的位置 两个用户之间聊天P2P
1.2 进程通信
进程在主机上运行的应用程序
在同一个主机内使用进程间通信机制通信操作系统定义不同主机通过交换**报文(Message)**来通信 使用OS提供的通信服务按照应用协议交换报文 借助传输层提供的服务
对于每对通信进程
一个标识为 客户端进程发起通信的进程
另一个为 服务器进程等待连接的进程
注意P2P架构的应用也有客户端进程和服务器进程之分
分布式应用进程需要解决的问题 问题1进程标示和寻址问题**服务用户**问题2传输层-应用层提供服务是如何**服务** 位置层间界面的SAPTCP/IP: socket形式应用程序接口APITCP/IPsocket API 问题3如何使用传输层提供的服务实现应用进程之间的报文交换实现应用**用户使用服务** 定义应用层协议报文格式解释时序等编制程序使用OS提供的API调用网络基础设施提供通信服务传报文实现应用时序等
1.2.1 问题1对进程进行编址addressing服务用户 进程为了接收报文必须有一个标识 即SAP发送也需要标示 主机唯一的32位IP地址 仅仅有IP地址不能够唯一标示一个进程在一台端系统上有很多应用进程在运行 所采用的传输层协议TCP or UDP端口号(Port Numbers) 一些知名端口号例子 HTTP: TCP 80 MailTCP25 ftpTCP2 一个进程用IP Port 标示 端节点 本质上一个主机进程之间的通信由2个端节点构成
1.2.2 问题2传输层提供的服务
1.2.2.1 需要穿过层间的信息 层间接口必须要携带的信息 要传输的报文对于本层来说SDU谁传的对方的应用进程的标示IP TCP(UDP) 端口传给谁对方的应用进程的标示对方的 IP TCP(IDP) 端口 传输层实体TCP 或者 UDP 实体根据这些信息进行 TCP报文段UDP 数据报的封装 源端口号目标端口号数据等将 IP 地址往下交 IP 实体用于封装 IP 数据报源 IP目标 IP
1.2.2.2 层间信息的代表
如果 Socket API 每次传输报文都携带如此多的信息太繁琐易错不便于管理用个代号标示通信的双方或者单方socket就像OS打开文件返回的句柄一样 对句柄的操作就是对文件的操作 TCP socket TCP 服务两个进程之间的通信需要之前要建立连接 两个进程通信会持续一段时间通信关系稳定 可以用一个整数表示两个应用实体之间的通信关系本地标示穿过层间接口的信息量最小TCP socket源IP源端口目标IP目标端口
1.2.2.3 TCP 之上的套接字socket
对于使用面向连接服务TCP的应用而言套接字是4元组的一个具有本地意义的标识。
4元组源IP源port目标IP目标port唯一的指定了一个会话2个进程之间的会话关系应用使用这个标示与远程的应用进程通信不必在每一个报文的发送都指定这4元组就像使用操作系统打开一个文件OS返回一个文件句柄一样以后使用这个文件句柄而不是使用这个文件的目录名、文件名简单便于管理
TCP 不只是一个简单标识它主要是用于指明应用进程会话的本地标识。 1.2.2.4 UDP socket
UDP socket
UDP 服务两个进程之间的通信需要之前无需建立连接 每个报文都是独立传输的前后报文可能给不同的分布式进程 因此只能用一个整数表示本应用实体的标示 因为这个报文可能传给另一个分布式进程 穿过层间接口的信息大小最小UDP socket本地IP本地端口但是传输报文时必须提供对方IPport 接收报文时传输层需要上传对方的IPport
1.2.2.5 UDP之上的套接字socket
对于使用无连接服务UDP的应用而言套接字是2元组的一个具有本地意义的标示 2元组IPport源端指定UDP 套接字指定了应用所在的一个端节点end point在发送数据报时采用创建好的本地套接字(标示ID)就不必在发送每个报文中指明自己所采用的 ip 和 port但是在发送报文时必须要指定对方的 ip 和 udp port(另外一个端节点) 1.2.2.6 套接字socket
进程向套接字发送报文或从套接字接收报文套接字-门户 发送进程将报文推出门户发送进程依赖于传输层设施在另外一侧的门将报文交付给接受进程接收进程从另外一端的门户收到报文(依赖于传输层设施) 1.2.3 如何使用传输层提供的服务实现应用 定义应用层协议报文格式、解释、时序等编制程序通过 API 调用网络基础设施提供通信服务传报文解析报文实现应用时序等
1.3 应用层协议
应用层协议定义了运行在不同端系统上的应用进程如何相互交换报文
交换的报文类型请求和应答报文各种报文类型的语法报文中的各个字段及其描述字段的语义即字段取值的含义进程何时、如何发送报文及对报文进行响应的规则
应用协议仅仅是应用的一个组成部分
公开协议
由RFC文档定义允许互操作如HTTPSMTP
专用(私有)协议:
协议不公开如Skype
1.3.1 应用需要传输层提供什么样的服务?如何描述传输层的服务?
数据丢失率
有些应用则要求100%的可靠数据传输如文件有些应用如音频能容忍一定比例一下的数据丢失
延迟
一些应用 处于有效性考虑对数据传输有严格的时间限制 Internet 电话、交互式游戏延迟、延迟差
吞吐
一些应用如多媒体必须需要最小限度的吞吐从而使得应用能够有效运转一些应用能充分利用可供使用的吞吐弹性应用
安全性
机密性完整性可认证性鉴别
常见应用对于传输服务的要求 1.3.2 Internet 传输层提供的服务
TCP 服务
可靠的传输服务流量控制发送方不会淹没接受方拥塞控制当网络出现拥塞时能抑制发送方不能提供的服务时间保证、最小吞吐保证和安全面向连接要求在客户端进程和服务器进程之间建立连接
UDP 服务
不可靠数据传输不提供的服务可靠、流量控制、拥塞控制、时间、带宽保证、建立连接
UDP 啥都没有那为什么有UDP呢
1.3.3 UDP 存在的必要性
能够区分不同的进程而IP服务不能 在IP提供的主机到主机端到端功能的基础上区分了主机的应用进程 无需建立连接省去了建立连接时间适合事务性的应用不做可靠性的工作例如检错重发适合那些对实时性要求比较高而对正确性要求不高的应用 因为为了实现可靠性(准确性、保序等)必须付出时间代价(检错重发)。 没有拥塞控制和流量控制应用能够按照设定的速度发送数据 而在TCP上面的应用应用发送数据的速度和主机向网络发送的实际速度是不一致的因为有流量控制和拥塞控制
1.3.4 Internet应用及其应用层协议和传输协议 1.3.5 安全TCP
TCP UDP
都没有加密明文通过互联网传输甚至密码
SSLsafe socket level运行在在TCP之上
在TCP上面实现提供加密的TCP连接私密性数据完整性端到端的鉴别
这就是为什么我们很多时候网页都是 https 开头
https http ssl SSL
------------httpSSL在应用层
应用采用SSL库SSL库使用TCP通信
SSL socket API
应用通过 API 将明文交给socketSSL将其加密在互联网上传输详见第8章
二、Web 和 HTTP
一些术语 Web页由一些对象组成 对象可以是一些HTML文件、JPEG图像、Java小程序、声音剪辑文件等 Web页含有一个基本的HTML文件该基本HTML文件又包含若干对象的引用链接 通过URL对每个对象进行引用 访问协议、用户名、口令字、端口等 URL格式
2.1 HTTP概况
HTTP超文本传输协议 Web 的 应用层协议客户/服务器模式 客户请求、接收和显示Web对象的浏览器服务器对请求进行响应发送对象的Web服务器 HTTP 1.0: RFC 1945HTTP 1.1: RFC 2068
使用TCP 客户发起一个与服务器的TCP连接(建立套接字)端口号为 80 服务器接受客户的TCP连接 在浏览器(HTTP客户端) 与 Web服务器(HTTP服务器 server) 交换HTTP报文 (应用层协议报文) TCP连接关闭
HTTP是无状态的
服务器并不维护关于客户的任何信息
维护状态的协议很复杂
必须维护历史信息(状态)如果服务器/客户端死机它们的状态信息可能不一致二者的信息必须是一致无状态的服务器能够支持更多的客户端
2.2 HTTP 连接
非持久HTTP连接
最多只有一个对象在TCP连接上发送下载多个对象需要多个TCP连接HTTP/1.0 使用非持久连接
持久HTTP
多个对象可以在一个(在客户端和服务器之间的) TCP 连接上的传输HTTP/1.1 默认使用持久连接
2.2.1 非持久HTTP连接 2.2.2 响应时间模型
**往返时间RTTround-trip time**一个小的分组从客户端到服务器再回到客户端的时间传输时间忽略不计 响应时间
一个RTT用来发起TCP连接一个RTT用来HTTP请求并等待HTTP响应文件传输时间
共2RTT 传输时间
2.2.3 持久HTTP
非持久HTTP的缺点
每个对象要2个 RTT操作系统必须为每个TCP连接分配资源但浏览器通常打开并行TCP连接以获取引用对象
持久HTTP
服务器在发送响应后仍保持 TCP 连接在相同客户端和服务器之间的后续请求和响应报文通过相同的连接进行传送客户端在遇到一个引用对象的时候就可以尽快发送该对象的请求
非流水方式的持久HTTP
客户端只能在收到前一个响应后才能发出新的请求每个引用对象花费一个RTT
流水方式的持久HTTP
HTTP/1.1的默认模式客户端遇到一个引用对象就立即产生一个请求所有引用(小)对象只花费一个RTT是可能的
2.3 HTTP 请求报文
两种类型的HTTP报文请求、响应HTTP请求报文 ASCII(人能阅读)
下面是一个典型的 HTTP 请求报文 虽然这个特定的报文仅有5行但一个请求报文能够具有更多的行或者至少为1行。
HTTP 请求报文的第一行叫做请求行(request line)其后继的行叫做首部行(header line)
请求行有3个字段方法字段、URL字段和HTTP版本字段
方法字段可以取不同的值包括GET、POST、HEAD、PUT 和 DELETE绝大多数HTTP请求报文使用GET方法
上面首部行的Host则指明了对方主机虽然该主机中已经有了TCP但是由于我们后面有 Connection:close要求不使用持久连接在发送完对象后就关闭连接所以指明主机还是必要的
2.3.1 通用格式 2.3.2 提交表单输入
例如用户向搜索引擎提供搜索关键词HTTP 客户端通常使用 POST 方法使用 POST 报文时用户仍然可以请求一个Web页面Web页面的特定内容依赖于用户的表单输入
使用 POST 方式实体中包含用户的输入而使用GET时实体为空不过GET也经常用来作为表单提交的方式 学过一些Web前端的话对这一点不会陌生form 可以指定提交的方式为 POST 或者是 GET 我们在 使用 PHP Web交互编程时是有 超全局数组 _POST 和 _GET的都可以获取用户的表单输入 POST方式
网页通常包括表单输入包含在实体主体entity body中的输入被提交到服务器
URL方式
方法GET输入通过请求行的URL字段上截
当使用GET比如我们输入了monkeys和bananas那么URL就会变成如下形式
www.somesite.comanimalsearch?monkeysbananas当然也有参数名参数值的形式比如我们网盘链接有passwordxxx
http://www.baidu.com/s?wdxxyyzzzcl3
参数wdcl
参数值xxyyzzz,32.3.3 方法类型
HTTP/1.0
GETPOSTHEAD 要求服务器在响应报文中不包含请求对象 - 故障跟踪
HTTP/1.1
GETPOSTHEADPUT 将实体主体中的文件上载到URL字段规定的路径 DELETE 删除URL字段规定的文件
2.4 HTTP响应报文
我们先看一条典型的 HTTP 响应报文 它有三个部分
初始状态行(state line) 状态行有3个字段协议版本字段、状态码和相应状态信息 6个首部行(head line) 每行含义和英文单词已知 实体体(entity body) 报文的主要部分
2.4.1 HTTP 响应状态码
位于服务器→客户端的响应报文中的首行
一些状态码的例子
200 OK
请求成功请求对象包含在响应报文的后续部分
301 Moved Permanently
请求的对象已经被永久转移了新的URL在响应报文的Location首部行中指定客户端软件自动用新的URL去获取对象
400 Bad Request
一个通用的差错代码表示该请求不能被服务器解读
404 Not Found
请求的文档在该服务上没有找到
505 HTTP Version Not Supported
2.4.2 Trying out HTTP (client side) for yourself
这里是在 终端中windows可以在cmd中通过telnet 连接目标服务器然后 输入一个 GET 请求报文
看看服务器的响应
例子 我自己瞎捣鼓了下
返回了一段 html 文本
rootLAPTOP-292TJJC6:~# telnet github.com 80
Trying 20.205.243.166...
Connected to github.com.
Escape character is ^].
GET /~ross/ HTTP/1.1
Host: github.com
HTTP/1.1 408 Request Time-out
Content-length: 110
Cache-Control: no-cache
Connection: close
Content-Type: text/htmlhtmlbodyh1408 Request Time-out/h1
Your browser didnt send a complete request in time.
/body/html
Connection closed by foreign host.
rootLAPTOP-292TJJC6:~#2.5 用户-服务器状态cookies
大多数主要的门户网站使用 cookies为什么我们打开以前打开过的网站能够恢复之前的信息
4个组成部分
在HTTP响应报文中有一个cookie的首部行在HTTP请求报文含有一个cookie的首部行在用户端系统中保留有一个cookie文件由用户的浏览器管理在Web站点有一个后端数据库
例子
Susan总是用同一个PC使用Internet Explore上网她第一次访问了一个使用了Cookie的电子商务网站当最初的HTTP请求到达服务器时该Web站点产生一个唯一的ID1678并以此作为索引在它的后端数据库中产生一个表项Susan 的浏览器收到该 HTTP 响应报文时它会看到 Set-cookie首部。从而在浏览器的 cookie 文件中添加一行该行包括了服务器的主机名和Set-cookie首部中的识别码当 Susan 后续再访问Amazon浏览器就会查询cookie 文件并抽取她对Amazon 的识别码放到HTTP 请求报文包括识别码的 cookie 首部行中。Amazon 就可以追踪 Susan 的访问活动提供服务
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
Cookies 能带来什么
用户验证购物车推荐用户状态Web e-mail
如何维持状态
协议端节点在多个事务上发送端和接收端维持状态cookieshttp报文携带状态信息
Cookies 与 隐私
Cookies 允许站点知道许多关于用户的信息可能将它知道的东西卖给第三方使用重定向和cookie 的搜索引擎还能知道用户更多的信息 如通过某个用户在大量站点上的行为了解其个人浏览方式的大致模式 广告公司从站点获得信息
2.6 Web 缓存代理服务器
Web 缓存器Web cache也叫代理服务器proxy server
目标不访问原始服务器就满足客户的要求
用户设置浏览器通过缓存访问Web浏览器将所有的HTTP请求发给缓存 在缓存中的对象缓存直接返回对象如对象不在缓存缓存请求原始服务器然后再将对象返回给客户端 缓存既是客户端又是服务器通常缓存是由ISP安装大学、公司、居民区ISP
为什么要使用Web缓存
降低客户端的请求响应时间可以大大减少一个机构内部网络与Internet 接入链路上的流量互联网大量采用了缓存可以使较弱的 ICP 也能够有效提供内容
示例 上图有两个网络机构内部网络和公共因特网
机构网络上一台服务器和因特网上的路由器通过 15Mbps 的链路连接对象平均长度1Mb机构内浏览器到初始服务器平均访问速率15个请求每秒我们假设HTTP请求报文小到可以忽略因而不计其在网络以及接入链路上的时延接入链路一侧路由器转发请求报文到接收响应报文我们称为“因特网时延”假设时间平均为2s
那么局域网上的流量强度为15个 / s * 1Mb / 100Mbps 0.15
接入链路上的流量强度15个 / s * 1Mb / 请求 / 15Mbps 1
流量强度为1排队时延无限大因而链路时延在分钟量级, 响应极慢
解决方式: 增加接入链路带宽, 不妨从15Mbps 升级到 100Mbps, 这样响应时间降低到大概2s 另一种方案, 在机构网络中安装Web缓存器, 我们这里假设命中率为0.4, 命中情况下时延在10ms以内, 此时链路只会处理60%的请求对象, 流量强度降低到0.6, 一般流量强度低于0.8 的时延为几十毫秒 那么 平均时延为 0.4 * 0.01 0.6 * 2.1 约等于 1.2 s
Web 缓存相较于升级链路, 代价低, 收益高
2.6.1 条件GET方法
缓存会涉及到 内容是否是最新的问题, 我们的HTTP请求报文中可以指明这一点 目标: 如果缓冲器中的对象拷贝是最新的, 就不要发送对象. 缓冲器: 在HTTP请求中指定缓存拷贝的日期 If-modified-since: date 服务器: 如果缓存拷贝陈旧, 则响应报文没包含对象: HTTP/1.0 304 Not Modified 三、FTP FTP(File Transfer Protocol), 即 文件传输协议.
向远程主机上传输文件或者 从远程主机接收文件客户/服务器模式 客户端: 发起传输的一方服务器: 远程主机 ftp: RFC 959ftp 服务器: 端口号为21
如果用过 Xfpt 进行 win 和 linux 之间的文件传输的话, 应该还是有一点熟悉的.
3.1 FTP: 控制连接与数据连接分开 FTP 客户端与 FTP服务器通过端口21联系, 并使用TCP为传输协议客户端通过控制连接获得身份确认客户端通过控制连接发送命令浏览远程目录收到一个文件传输命令时, 服务器打开一个到客户端的数据连接一个文件传输完成后, 服务器关闭连接服务器主动打开第二个TCP数据连接用来传输另一个文件控制连接: 带外(“out of bound”) 传送FTP 服务器维护用户的状态信息: 当前路径, 用户账户 与 控制连接 对应 有状态
3.2 FTP 命令, 响应
命令样例
在控制连接上以ASCII文本方式传送USER usernamePASS passwordLIST: 请服务器返回远程主机当前目录的文件列表RETR filename: 从远程主机的当前目录检索文件**(gets)**STOP filename: 向远程主机的当前目录存放文件**(puts)**
返回码样例
状态码和状态信息(同HTTP)331 Username OK, password required125 data connection already open; transfer starting425 Can’t open data connection452 Error writing file
四、Email
3个主要组成部分
用户代理邮件服务器简单邮件传输协议SMTP
用户代理
又名 “邮件阅读器”撰写、编辑和阅读邮件如 Outlook、Foxmail 就是用户代理输出和输入邮件保存在服务器上 4.1 Email邮件服务器 邮件服务器
邮箱中管理和 维护发送给用户的邮件输出报文队列 保持待发送邮件报文邮件服务器之间的SMTP协议发送email 报文 客户发送方邮件服务器服务器接收端邮件服务器
4.2 EmailSMTP[RFC 2821]
使用TCP在客户端和服务器之间传送报文端口号为25直接传输: 从发送方服务器到接收方服务器传输的3个阶段传输的3个阶段 握手传输报文关闭 命令/响应交互 命令: ASCII文本响应: 状态码和状态信息 报文必须为7位ASCII码
举例Alice 给 Bob 发送报文
Alice使用用户代理撰写邮件 并发送给 bobsomeschool.eduAlice的用户代理将邮件发送到她的邮件服务器;邮件放在报文队列中SMTP的客户端打开到Bob邮件服务器的TCP连接SMTP客户端通过TCP连接发送Alice的邮件Bob的邮件服务器将邮件放到Bob的邮箱Bob调用他的用户代理阅读邮件 4.3 简单的SMTP交互
客户的主机名crepes.fr服务器的主机名hamburger.eduC开头的ASCII码文本行是客户交给TCP套接字的那些行S开头的那些行是服务器发给TCP套接字的那些行
一旦建立TCP连接就会进行下面过程 客户从邮件服务器crepes.fs 向 邮件服务器 hamburger.edu 发送了一个报文Do you like ketchup? How about pickles?HELO, MAIL FROM, RCPT TO, DATA, QUIT 都是一些命令 . 表示结束
4.4 SMTP 总结
SMTP使用持久连接SMTP要求报文(首部和主体)为7位ASCII编码SMTP服务器使用 CRLF.CRLF决定报文的尾部
HTTP比较:
HTTP: 拉(pull)用户通过HTTP 拉取信息SMTP: 推(push)发送邮件服务器把文件推向接收邮件服务器二者都是ASCII形式的命令/响应交互、状态码HTTP: 每个对象封装在各自的响应报文中SMTP: 多个对象包含在一个报文中
4.5 邮件报文格式 SMTP交换Email 报文的格式
RFC 822文本报文的标准 首部行如 To: From: Subject: 与SMTP 命令 不同 主体 报文只能是ASCII码字符
4.6 报文格式多媒体扩展
如果传输的内容不满足ascii我们就需要进行一些扩展。 MIME多媒体邮件扩展multimedia mail extension RFC 20452056 在报文首部用额外的行申明MIME内容类型 base64 编码方式就是 一种 将不满足 ASCII 的字符 编码成更长的 字符从而能够通过SMTP的协议传输
4.7 邮件访问协议 SMTP传送到接收方的邮件服务器邮件访问协议从服务器访问邮件 POP邮局访问协议Post Office Protocol[RFC 1939] 用户确认代理 – 服务器身份并下载 IMAPInternet 邮件访问协议**Internet Mail Access Protocol[RFC 1730]** 更多特性更复杂在服务器上处理存储的报文 HTTPHotmailYahooMail 等 方便
4.7.1 POP3协议 事务处理过程POP3的用户代理通常被用户配置为“下载并删除” / “下载并保留” 方式。
如上面 retr 之后 就 dele 了问题是邮件接收方可能是移动的在一台机器接收后在其它机器却无法访问因为用户报文已经被删除了
下载并保留模式则支持在不同机器重新读取邮件因为邮件仍然保存在邮件服务器上。
4.7.2 POP3 与 IMAP协议
POP3本地管理文件夹
先前的例子使用 **“下载并删除”**模式。
如果改变客户机Bob不能阅读邮件“下载并保留”不同客户机上为报文的拷贝POP3在会话中是无状态的
IMAP 远程管理文件夹
IMAP服务器将每个报文与一个文件夹联系起来允许用户用目录来组织报文允许用户读取报文组件IMAP在会话过程中保留用户状态 目录名、报文ID与目录名之间映射
五、DNS
5.1 DNS 的必要性
如何标记主机
主机名hostnamewww.facebook.com 等但是它们几乎没有提供主机在因特网中的信息IP地址不便于人记忆因而 存在着“字符串”主机名——IP地址的转换的必要性人类用户提供要访问机器的“字符串”名称由DNS负责转换成为二进制的网络地址
5.2 DNS(domain name system) 系统需要解决的问题
问题1如何命名设备
用有意义的字符串好记便于人类用使用解决一个平面命名的重名问题层次化命名
问题2如何完成名字到IP地址的转换
分布式的数据库维护和响应名字查询
问题3如何维护增加或者删除一个域需要在域名系统中做哪些工作
5.3 DNS 的历史
ARPANET的名字解析解决方案 主机名没有层次的一个字符串**(一个平面)**存在着一个(集中)维护站维护着一张主机名——IP地址的映射文件Hosts.txt每台主机定时从维护站取文件 ARPANET解决方案的问题 当网络中主机数量很大时 没有层次的主机名称很难分配文件的管理、发布、查找都很麻烦
5.4 DNS(Domain Name system)总体思路和目标
DNS的主要思路 分层的、基于域的命名机制若干分布式的数据库完成名字到 IP 地址的转换运行在UDP之上端口号为53的应用服务核心的Internet功能但以应用层协议实现 在网络边缘处理复杂性 DNS主要目的 实现主机名-IP地址的转换(name/IP translate)其它目的 主机别名到规范名字的转换Host aliasing邮件服务器别名到邮件服务器的正规名字的转换Mail server aliasing负载均衡Load Distribution
5.5 问题1DNS名字空间The DNS Name Space DNS域名结构 一个层面命名设备会有很多重名 DNDS采用层次树状结构的 命名方法 Internet 根被划为几百个顶级域(top lever domains) 通用的(generic) .com.edu; .gov; int; .mil; .net; .org firm.hsop ; .web ; .arts; .rec ; 国家的(countries) .cn; .us; .nl; .jp 每个(子)域下面可划分为若干子域(subdomains)** 树叶是主机
5.5.1 DNS: 根名字服务器 根DNS服务器有400多个根名字服务器遍及全球由13个不同的组织分别管理
根名字服务器提供TLD服务器的IP地址
5.5.2 DNS 名字空间 域名(Domain Name) 从本域往上直到树根中间使用 “.” 间隔不同的级别例如ustc.edu.cnauto.ustc.edu.cnwww.auto.ustc.edu.cn域的域名可以用于表示一个域主机的域名一个域上的一个主机 域名的管理 一个域管理其下的子域 .jp 被划分为 ac.jpco.jp .cn 被划分为 edu.cn com.cn 创建一个新的域必须征得它所属域的同意 域与物理网络无关 域遵从组织界限而不是物理网络 一个域的主机可以不在一个网络一个网络的主机不一定在一个域 域的划分是逻辑的而不是物理的
5.6 问题2解析问题——名字服务器Name Server
一个名字服务器的问题 可靠性问题单点故障扩展性问题通信容量维护问题远距离的集中式数据库 区域zone 区域的划分由区域管理者自己决定将DNS名字空间划分为互不相交的区域每个区域都是树的一部分名字服务器 每个区域都有一个名字服务器维护着它所管辖区域的权威信息authoritative record名字服务器允许被放置在区域之外以保障可靠性
5.6.1 名字空间划分为若干区域Zone 权威DNS服务器组织机构的DNS服务器提供组织机构服务器(如Web和mail)可访问的主机和IP之间的映射
组织机构可以选择实现自己维护或由某个服务提供商来维护
5.6.2 TLD 服务器
顶级域(TLD)服务器负责顶级域名(如comorgnetedu和gov)和所有国家级的顶级域名(如cnukfrcajp
Network solutions 公司维护 com TLD服务器Educause 公司维护 edu TLD服务器
5.6.3 区域名字服务器维护资源记录
资源记录(resource records) 作用维护 域名-IP地址(其它)的映射关系位置Name Server的分布式数据库中 RR格式(domain_namettltypeclassValue) Domain_name域名Ttltime to live生存时间(权威缓冲记录)Class 类别对于Internet值为INValue 值可以是数字域名或ASCII串Type 类别资源记录的类型详见下面
DNS 记录
DNS保存资源记录(RR)的分布式数据库 RR格式namevaluetypettl name 和 value 取决于 type 的类别 Type A name 为主机value 为 IP 地址 Type NS name 域名如foo.comvalue 为该域名的权威服务器的域名 Type CNAME name 为规范名字的别名 www.ibm.com 的 规范名字为servereast.backup2.ibm.com value 为规范名字 Type MX value 为 name 对应的邮件服务器的名字
TTL生存时间决定了资源记录应当从缓存中删除的时间
资源记录resource records的 一个例子 5.6.4 DNS(Domain Name System)
DNS 大致工作过程 应用调用 解析器parser解析器作为客户 向 Name Server 发出查询报文封装在UDP段中Name Server 返回响应报文name/ip 5.6.5 本地名字服务器Local Name Server
并不严格属于层次结构每个ISP居民区的ISP、公司、大学都有一个本地DNS服务器 也称为默认名字服务器 当一个主机发起一个DNS查询时查询被送到其本地DNS服务器 起着代理的作用将查询转发到层次结构中
5.6.6 ★递归查询 名字解析过程 目标名字在 Local Name Server 中 情况1查询的名字在该区域内部情况2缓存cashing
当与本地名字服务器不能解析名字时联系根名字服务器顺着根-TLD 一直找到 权威名字服务器 名字解析负担都放在了当前联络的名字服务器上问题根服务器的负担太重解决迭代查询iterated queries
5.6.7 迭代查询 主机 cis.poly.edu 想知道 主机 gaia.cs.umass.edu 的IP地址根(及各级域名)服务器返回的不是查询结果而是下一个NS的地址最后由权威名字服务器给出解析结果当前联络的服务器给出可以联系的服务器的名字“我不知道这个名字但可以向这个服务器请求”
5.6.8 DNS 协议、报文
DNS 协议查询和响应报文的报文格式相同通过标志位来判断是查询还是应答 5.6.9 提高性能缓存
一旦名字服务器学到了一个映射就将该映射缓存起来根服务器通常都在本地服务器中缓存着 使得根服务器不用经常被访问 目的提高效率可能存在的问题如果情况变化缓存结果和权威资源记录不一致解决方案TTL默认2天
5.7 问题3维护问题新增一个域 在上级域的名字服务器中增加两条记录指向这个新增的子域的域名 和 域名服务器的地址 在新增子域 的名字服务器上运行名字服务器负责本域的名字解析名字 - IP地址 例子在 com域 中建立一个“Network Utopia” 到注册登记机构注册域名 networkutopia.com 需要向该机构提供权威DNS服务器(基本的、和辅助的)的名字和IP地址 登记机构在com TLD服务器中插入两条RR记录 (networkutopia.comdns1.networkutopia.comNS) (dns1.networkutopia.com212.212.212.1A) 在 networkutopia.com 的权威服务器中确保有 用于Web服务器的 www.networkuptopia.com 的类型为A的记录用于邮件服务器 mail.networkutopia.com 的类型为MX的记录
5.7.1 攻击DNS
DDoS 攻击 对根服务器进行流量轰炸 攻击发送大量ping 没有成功原因1根目录服务器配置了流量过滤器防火墙原因2Local DNS 服务器 缓存了TLD服务器的IP地址因此无需查询根服务器 向TLD服务器流量轰炸攻击发送大量查询 可能更危险效果一般大部分DNS缓存了TLD
重定向攻击 中间人攻击 截获查询伪造回答从而攻击某个(DNS回答指定的IP)站点 DNS中毒 发送伪造的应答给DNS服务器希望它能够缓存这个虚假的结果 技术上较困难分布式截获和伪造 利用DNS基础设施进行DDoS 伪造某个IP进行查询攻击这个目标IP 查询放大响应报文比查询报文大 效果有限
总之DNS 有着很强的健壮性至今为止还没有一个攻击成功地妨碍了DNS服务。
因而那些对于13个根服务器没有一个在中国的阴谋论在很大程度上是没必要担忧的。
六、P2P应用
6.1 纯P2P架构 没有(或极少)一直运行的服务器任意端系统都可以直接通信利用peer的服务能力Peer节点间歇上网每次IP地址都有可能变化
例子
文件分发(BitTorrent)流媒体(KanKan)VoIP(Skype)
6.2 文件分发C/S vs P2P 问题从一台服务器分发文件大小F到N个peer需要多少时间
Peer节点上下载能力是有限的资源
6.2.1 文件分发时间C/S模式 服务器传输都是由服务器发送给peer服务器必须顺序传输 (上载) N个文件拷贝 发送一个copyF / u发送N个copyNF / u 客户端每个客户端必须下载一个文件拷贝 dmin 客户端最小的下载速率下载带宽最小的客户端下载的时间F / dmin
采用 C/S 方法将一个F大小的文件分发给N个客户端的最小分发时间 D C / S ≥ m a x { N F / u s , F / d m i n } D_{C/S} \ge max\{NF / u_s , F/d_{min} \} DC/S≥max{NF/us,F/dmin}
因为 服务器要发N份然后每个客户端都要下载
随着N 的增大最小分发时间线性增长
6.2.2 文件分发时间P2P模式
服务器传输最少需要上载一份拷贝 发送一个拷贝的时间F/u 客户端每个客户端必须下载一个拷贝 最小下载带宽客户端耗时F/dmin 客户端所有客户端总体下载量NF 最大上载带宽是 u s Σ u i u_s \Sigma u_i usΣui除了服务器可以上载其他所有的 peer 节点都可以上载
采用P2P方法发送一个F大小的文件分发给N个客户端耗时 D P 2 P ≥ m a x ( F / u s , F / d m i n , N F / ( u s Σ u i ) ) D_{P2P} \ge max(F/u_s, F/d_{min}, NF/(u_s \Sigma u_i)) DP2P≥max(F/us,F/dmin,NF/(usΣui))
随着N 的增加虽然NF增加但是每个peer节点也会带来上载带宽因此此时不是随着N线性增加了
6.2.3 Client-server vs. P2P
$ 客户端上载速率 uF / u 1小时u_s 10ud_{min} u_s $ 6.2.4 P2P文件共享
例子
Alice在其笔记本电脑上运行P2P客户端程序间歇性地连接到 Internet每次从其ISP得到新的IP地址请求“双截棍.MP3”应用程序显示其他有 “双截棍.MP3” 拷贝的对等方Alice选择其中一个对等方如Bob.文件从 Bob’s PC 传送到 Alice 的笔记本上HTTP当 Alice 下载时其他用户也可以从 Alice 处下载Alice 的对等方既是一个 Web 客户端也是一个瞬时 Web 服务器
所有的对等方都是服务器 可扩展性好!
两大问题 如何定位所需资源如何处理对等方的加入与离开 可能的方案 集中分散半分散
6.2.5 非结构化P2P
6.2.5.1 P2P集中式目录
最初的 “Napster” 设计 当对等方连接时它告知中心服务器 TP地址 内容 Alice 查询 “双截棍.MP3” Alice 从 Bob 处请求文件 存在的问题
单点故障性能瓶颈侵犯版权
文件传输是分散的而定位内容则是高度集中的
6.2.5.2 查询洪泛Gnutella完全分布式
全分布式 没有中心服务器 开放文件共享协议许多Gnutella客户端实现了Gnutella协议 类似HTTP有许多的浏览器 覆盖网络图如果x和y之间有一个TCP连接则二者之间在一条边所有活动的对等方和边就是覆盖网络边并不是物理链路给定一个对等方通常所连接的节点少于10个
Gnutella协议 在已有的TCP连接上发送查询报文对等方转发查询报文以反方向返回查询命中报文
我们称这种查询方式为 洪泛flooding。
显然我们的查询会不断向外扩展当规模太大的时候压力很大。
我们可以通过tlltime to live缓存等手段来改善但显然这种完全分布式的P2P 管理方式较难维护。
Gnutella对等方加入 对等方 x 必须首先发现某些已经在覆盖网络中的其他对等方使用可用对等方列表 自己维持一张对等方列表经常开机的对等方的IP 联系维持列表的 Gnutella 站点 x 接着试图与该列表上的对等方建立 TCP 连接直到与某个对等方 y 建立连接 x 向 y 发送一个Ping报文y 转发该Ping报文 所有收到Ping报文的对等方以 Pong报文响应 IP地址、共享文件的数量及总字节数 x 收到许多Pong报文然后它能建立其他TCP连接
6.2.5.3 利用不匀称性KaZaA混合体 每个对等方要么是一个组长要么隶属于一个组长 对等方与其组长之间有TCP连接组长对之间有TCP连接 组长跟踪其所有的孩子的内容组长与其他组长联系 转发查询到其他组长获得其他组长的数据拷贝
可见 组长间是 P2P而组员和组长间是C/S
KaZaA查询
每个文件有一个散列标识码和一个描述符客户端向其组长发送关键字查询组长用匹配进行响应 对每个匹配元数据、散列标识码和IP地址 如果组长将查询转发给其他组长其他组长也以匹配进行响应客户端选择要下载的文件 向拥有文件的对等方发送一个带散列标识码的 HTTP请求
6.2.5.4 P2P文件分发BitTorrent
BitTorrent 是一个很常见的东西我们平时在BT网站下载电影BT磁力链接……
BitTorrent 是一种用于文件分发的流行P2P协议。
参与一个特定文件分发的所有对等方的集合被称为一个洪流(torrent)。
一个洪流中的对等方彼此下载等长度的文件块chunk典型长度为256KB。
文件被分为一个个块 256KB而对于是否拥有某个块用位图bitmap来维护网络中的这些 peers 发送接收文件块相互服务 Peer 加入 torrent 一开始没有块但是将会通过其他节点处累积文件块向**跟踪服务器Tracker**注册获得 peer 节点列表和部分 peer 节点构成邻居关系“连接”周期性的通知Tracker 自己仍然在洪流中 当peer下载时该 peer 可以同时向其他节点提供上载服务 Peer可能会变换用于交换块的 peer 节点 扰动churnpeer 节点可能会上线或者下线 一旦一个 peer 拥有整个文件它会(自私的)离开或者保留(利他主义)在 torrent 中
BitTorrent请求发送文件块
请求块
在任何给定时间不同 peer 节点拥有一个文件块的子集周期性的Alice节点向邻居询问他们拥有哪些块的信息Alice 向 peer 节点请求它希望的块稀缺的块
发送块一报还一报tit-for-tat
Alice向 4 个 peer 发送块这些块向它自己提供最大带宽的服务也就是说向对自己好的邻居发送块 其他 peer 被Alice阻塞(将不会从Alice处获得服务)每10秒重新评估一次前4位 每个30秒随机选择其他peer节点向这个节点发送块 “优化疏通”这个节点新选择的节点可以加入这个top
所以我们平时用的BT是如何工作的呢
用户在搜索引擎上查询下载 torrent 文件torrent 文件中包含了 tracking server 的信息向 tracking server 发送请求然后会返回一个peer列表我们再和这些 peer 进行通信
6.2.6 DHT(结构化P2P)
DHT 即 分布式散列表它是一种简单的数据库数据库记录分布在一个P2P系统的多个对等方上。
每个节点拥有一个哈希值然后根据哈希值的大小将节点组成一个有序的拓扑环状结构。
而文件也有哈希值也按照类似的方法按照哈希值从小到大将文件分组存放在某个对等方上。
七、CDN
7.1 视频流化服务和CDN上下文 视频流量:占据着互联网大部分的带宽 NetflixYouTube占据37%16%的ISP下行流量。~1B(billion) YouTube 用户~75M Netflix用户 挑战规模性-如何服务者~1B 用户? 单个超级服务器无法提供服务(为什么) 挑战异构性 不同用户拥有不同的能力(例如有线接入和移动用户带宽丰富和受限用户) 解决方案分布式的应用层面的基础设施
7.2 多媒体视频
视频固定速度显示的图像序列 e.g.24 images/sec 网络视频特点 高码率10x于音频高的网络带宽需求可以被压缩90%以上的网络流量是视频 数字化图像像素的阵列 每个像素被若干bits表示 编码使用图像内和图像间的冗余来降低编码的比特数 空间冗余(图像内)时间冗余(相邻的图像间) **CBR(constant bitrate)**以固定速率编码**VBR(variable bitrate)**视频编码速率随时间的变化而变化例子 MPEG1 (CD-ROM) 1.5MbpsMPEG2 (DVD) 3-6 MbpsMPEG4 (often used in Internet 1 Mbps)
下面是空间编码和时间编码的例子 7.3 存储视频的流化服务
简单场景
我们在看视频的方式难道要把视频全部下载下来再看吗
事实上我们是通过流化服务边下边看。 7.3.1 多媒体流化服务DASH
DASHDynamicAdaptive Streaming over HTTP服务器 将视频文件分割成多个块每个块独立存储编码于不同码率(8-10种)告示文件(manifest file)提供不同块的URL 客户端 先获取告示文件周期性地测量服务器到客户端的带宽查询告示文件在一个时刻请求一个块HTTP头部指定字节范围 如果带宽足够选择最大码率的视频块会话中的不同时刻可以切换请求不同的编码块(取决于当时的可用带宽)
7.3.2 流式多媒体技术3DASH
“智能”客户端客户端自适应决定 什么时候去请求块(不至于缓存挨饿或者溢出)请求什么编码速率的视频块(当带宽够用时请求高质量的视频块)哪里去请求块(可以向离自己近的服务器发送URL或者向高可用带宽的服务器请求)
7.4 内容分发网Content Distribution Networks
挑战服务器如何通过网络向上百万用户同时流化视频内容上百万视频内容选择1单个的、大的超级服务中心“mega-server” 服务器到客户端路径上跳数较多瓶颈链路的带宽小导致停顿“二八规律”决定了网络同时充斥着同一个视频的 多个拷贝效率低付费高、带宽浪费、效果差单点故障点性能瓶颈周边网络的拥塞
评述相当简单但是这个方法不可扩展 选择2通过CDN全网部署缓存节点存储服务内容就近为用户提供服务提高用户体验 enter deep将CDN服务器深入到许多接入网 更接近用户数量多离用户近管理困难Akamai, 1700个位置 bring home部署在少数(10个左右)关键位置如将服务器簇安装于POP附近离若干1st ISP POP较近 采用租用线路将服务器簇连接起来Limelight CDN在 CDN 节点中存储内容的多个拷贝让内容靠近用户 e.g. Netflix stores copies of MadMen 用户从CDN中请求内容 重定向到最近的拷贝请求内容如果网络路径拥塞可能选择不同的拷贝 OTT 挑战在拥塞的互联网上复制内容 从哪个CDN节点中获取内容?用户在网络拥塞时的行为?在哪些CDN节点中存储什么内容?
CDN“简单”内容访问场景
Bob(客户端)请求视频http://netcinema.com/6Y7B23V
视频存储在CDN位于http://KingCDN.com/NetC6yB23V
大致过程就是主机访问本地DNS服务器然后做了一个迭代查询最终一直到CDN权威服务器然后由KingCDN内容分发服务器将内容发送到主机 案例学习Netflix Netflix 维护了一个账户注册的服务器然后租了 Amazon 的云服务器视频制作在 云服务器上进行视频制作网页也放在了云服务器上制作完成后上传到CDN用户完成账户注册后点击链接重定向进行重定向然后获得了缓存节点用户可以去选择一个CDN 缓存节点也可以自动分配然后从CDN缓存节点获得 流化服务
八、TCP/IP Socket编程快速入门
大黑书上接着就开始讲套接字编程了想着还是实践下比较好所以这里写一下怎样通过 Python 使用 Socket
先回顾一下
socket 是一套用于不同主机间通信的 API工作在 TCP/IP 协议栈之上
我们的浏览器Appssh客户端都是基于 socket 来实现的
为了进行主机间的通信我们需要指明 IP地址 和 端口号IP地址很好理解而 端口号主要为了 OS 区分数据发送到哪个应用上
TCP 是可靠数据传输我们发送数据对方一定能收到。
TCP 要求 数据收发双方扮演不同角色服务器和客户端服务器等待客户端连接
下面就在 Pycharm 上进行一个简单的体验
8.1 创建简单服务器
这个服务器只需将收到的消息原封不动地发回去
import socketwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind((0.0.0.0, 1234))s.listen()c, addr s.accept()with c:print(addr, connected.)while True:data c.recv(1024)if not data:breakc.sendall(data)with 是语法糖语句块结束自动调用 s.close()
下面是 socket 的构造函数
def __init__(self, family-1, type-1, proto-1, filenoNone):我们传入的 AF_INET 指明了家族(family) 是 IPv4 的地址家族address family
SOCK_STREAM 则指明我们用的是 TCP 协议对应的是type 协议STREAM其实代表了 TCP 是一个流式协议我们会在后面的章节中学到
然后通过 bind() 函数将我们创建的socket 关联到主机的某一个网卡又网路接口/network interface和 端口 上
”0.0.0.0“ 这里单纯代表主机上任意一个网卡都可以使用这个 socket 进行通信
listen 则将 socket 置为监听状态并等待客户端连接
accept 则会返回一个新的socket 上面的 c 和 IP地址上面的 addr
我们 在 WSL 中通过netcatlinux 下可以用来读写 TCP/UDP 数据的命令行工具以 本地ip 作为回送地址连接端口号1234
结果 8.2 客户端
客户端向服务器请求连接然后发送数据并接收服务器返回的数据并打印
import socketwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.connect((127.0.0.1, 1234))s.sendall(bHello, world!)data s.recv(1024)print(fReceived: {data})结果 8.3 并发多客户端通信
TCP是一个四元组天生支持我们区分多客户端对于同一端口或者不同端口的访问我们自然可以实现并发多客户端通信
对于 具体到哪个进程可以由Pid 区分这就是 OS的事情了
8.3.1 多线程的Socket 服务器
我们前面的服务器一次只能和一个客户端通信对于并发多客户端通信我们这里采用最简单的方式多线程
import socket
import threadingdef handle_client(c, addr):print(addr, connected.)while True:data c.recv(1024)if not data:breakc.sendall(data)with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind((0.0.0.0, 1234))s.listen()while True:c, addr s.accept()t threading.Thread(targethandle_client, args(c, addr))t.start()
循环等待连接然后将 新开线程去进行通信
结果 但是由于 Python GILGlobal Interpreter Lock的存在Python 中的线程做不到真正的并发而且线程本身也会占用额外的系统资源
除了线程外我们还可以使用基于事件驱动的 selectors 来实现多个连接的并发或者通过更高层的 asyncio 来实现异步的 socket 代码。
这里不再介绍
8.4 简易HTTP服务器
那么 HTTP 服务器是如何实现的呢
HTTP 是 TCP 协议的典型应用也是 浏览器和 服务器交互的主要方式
服务器通常监听80端口然后等待客户端连接
前面我们也介绍了客户端发送请求报文服务发送响应报文 我们随便写一个 html 的页面然后存到我们的工作目录下
主函数体我们切换下工作目录然后和前面一样死循环监听
if __name__ __main__:# Change working directory to script folderos.chdir(os.path.dirname(os.path.abspath(__file__)))with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind((0.0.0.0, 1234))s.listen()while True:c, addr s.accept()t threading.Thread(targethandle_client, args(c, addr))t.start()
服务逻辑
接收 http 头部如果没有指定文件我们就重定向到 之前写的html文件尝试打开目标文件读取内容返回内容如果文件不存在返回404
def handle_client(c, addr):print(addr, connected.)with c:request c.recv(1024)# parse HTTP headersheaders request.split(b\r\n)file headers[0].split()[1].decode()# Load file contentif file /:file /index.htmltry:with open(WEBROOT file, rb) as f:content f.read()response bHTTP/1.0 200 OK\r\n\r\n contentexcept FileNotFoundError:response bHTTP/1.0 404 NOT FOUND\r\n\r\nFile not found!# Send HTTP responsec.sendall(response)我们可以在浏览器内输入服务器 IP地址 端口号来发送请求
结果 如果我们指定了一个不存在的文件 九、TCP 套接字编程
通过 P8大致了解了服务器和客户端之间是如何通过 Sokcet 来传输报文的。下面进入大黑书关于这一部分的内容。
9.1 Socket 编程
应用进程使用传输层提供的服务才能够交换报文实现应用协议实现应用
TCP / IP应用进程使用Socket API 访问传输服务地点界面上的SAPSocket方式Socket API
目标“学习如何构建能借助 socket 进行通信的 C/S 应用程序
socket分布式应用进程之间的门传输层协议提供的端到端服务接口 2种传输层服务的socket类型
TCP可靠的、字节流的服务UDP不可靠数据UDP数据包服务
9.2 TCP套接字编程
套接字应用进程与端到端传输协议TCP或UDP之间 的门户
TCP服务从一个进程向另一个进程可靠地传输字节流
服务器首先运行等待连接建立
1.服务器进程必须先处于运行状态
创建欢迎socket和本地端口捆绑bind在欢迎socket 上阻塞式等待接收用户的连接
客户端主动和服务器建立连接
创建客户端本地套接字隐式捆绑到本地 指定服务器进程的IP地址和端口号与服务器进程连接 当与客户端连接请求到来时 服务器**接受accept**来自用户端的请求解除阻塞式等地返回一个新的sokcet与欢迎 socket 不一样与客户端通信 允许服务器与多个服务器通信使用源IP和源端口来区分不同的客户端 连接API调用有效时客户端 P 与 服务器建立了TCP连接
从应用程序的角度 TCP在客户端和服务器进程之间 提供了可靠的、字节流管道服务 C/S模式的应用样例 客户端从标准输入装置 读取一行字符发送给服务器服务器从 socket 读取字符服务器将字符转换成大写然后返回给客户端客户端从socket中读取一行字符然后打印出来
实际上这里描述了C-S之间交互的动作次序
下面这个交互过程的例图其实就和我们前面写的python程序差不多 9.3 数据结构 sockaddr_in
IP 地址和 port 捆绑关系的数据结构标示进程的端节点
这个和 python 中的命名很类似意义不再赘述
struct sockaddr_in{short sin_family; // AF_INTEu_short sin_port; // portstruct in_addr sin_addr; // IP address, unsigned longchar sin_zero[8]; // align
};9.4 数据结构 hostent
域名和IP地址的数据结构
struct hostent {char *h_name;char **h_aliases; // 域名别名int h_addrtype;int h_length; // 地址长度char **h_addr_list; // IP 地址列表#define h_addr h_addr_list[0]; // 解析后的IP地址
};hostent 作为调用域名解析函数时的参数返回后将 IP 地址拷贝到 socketaddr_in 的 IP 地址部分
9.5 例子C客户端(TCP) sockaddr存 服务器 IP 和 相应端口号clientSocket客户端 socket就是一个整数prth指向一个 hostent 对象的指针Sentence / modifiedSentencehost服务器域名port端口号atoiascii to int即str to int然后创建 socket指定地址族PF_INETSOCK_STREAM等 清空sad然后对其赋值通过host 来初始化 ptrhhostname to IP address拿到ptrh后把IP放到 sad内 然后建立连接
整个过程 9.6 例子C服务器(TCP) sad服务器 IP 及 portcad客户端 IP 及 portwelcomeSocket / connectionSocket欢迎socket 和 建立连接后的新socketptrh和前面类似port端口号初始化welcomeSocket 然后清空sad对其初始化本地 IPPort 进行 bindIPPort然后 阻塞等待连接 accept建立 connectionSocket读 报文 到 clientSentence将 capitalizedSentence 写回 关闭 socket
当然这个逻辑每次只能进行一个客户端的通信并发通信的方式自行了解
十、UDP 套接字编程
UDP在客户端和服务器之间 没有连接
没有握手发送端在每一个报文中明确地指定目标的IP地址和端口号服务器必须从收到的分组中提取出发送端的IP地址和端口号
UDP传送的数据可能乱序也可能丢失
进程视角看UDP服务 UDP 为客户端和服务器提供不可靠的字节组的传送服务 10.1 Client/server socket 交互UDP 服务器创建socket然后进行bind和 TCP 不同的是这里没有了connect 步骤 Client 直接发送数据报 服务器读请求服务器应答客户端读应答
10.2 样例C客户端UDP 流程描述 1.3 样例C服务器(UDP) 流程描述