You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Web 的应用层协议是超文本传输协议(HyperText Transfer Protocol,HTTP),它是Web的核心,在[RFC 1945] 和 [RFC 2616] 中进行了定义。HTTP由两个程序实现:一个客户端程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP定义了这些报文的结构以及客户和服务器进行报文交换的方式。
fromsocketimport*serverName='127.0.0.1'serverPort=12000clientSocket=socket(AF_INET, SOCK_STREAM)
# Connect the socket to a remote address.clientSocket.connect((serverName, serverPort))
while1:
sentence=raw_input('TCP:Input lowercase sentence:')
# Send a data string to the socket.clientSocket.send(sentence)
# Receive up to buffersize bytes from the socket.modifiedSentence=clientSocket.recv(1024)
print'From Server:', modifiedSentenceifsentencein ['exit', 'quit']:
print'Bye!'breakclientSocket.close()
TCPServer
importthreadingfromsocketimport*serverPort=12000deftcp(sock, addr):
while1:
sentence=sock.recv(1024)
print'Received from %s:%s.'%addrprint'Message: %s'%sentencecapitalizedSentence=sentence.upper()
sock.send(capitalizedSentence)
ifsentencein ['exit', 'quit']:
print'Bye!'breaksock.close()
print'Connection from %s:%s closed.'%addrserverSocket=socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('127.0.0.1', serverPort))
# Enable a server to accept connections.serverSocket.listen(5)
print'The TCP server is ready to receive'while1:
# Wait for an incoming connection.connectionSocket, addr=serverSocket.accept()
t=threading.Thread(target=tcp, args=(connectionSocket, addr))
t.start()
UDP套接字编程
UDPClient
fromsocketimport*serverName='127.0.0.1'servePort=12000# IPv4 & UDPclientSocket=socket(AF_INET, SOCK_DGRAM)
whileTrue:
message=raw_input('UDP:Input lowercase sentence:')
# Send a data string to socketclientSocket.sendto(message, (serverName, servePort))
# Receive up to buffersize bytes from the socketmodifiedMessage, serveAddress=clientSocket.recvfrom(2048)
print'From Server:', modifiedMessageifmessagein ['exit', 'quit']:
print'Bye!'breakclientSocket.close()
UDPServer
fromsocketimport*serverPort=12000serverSocket=socket(AF_INET, SOCK_DGRAM)
# Bind the socket to a local address.serverSocket.bind(('127.0.0.1', serverPort))
print"This UDP server is ready to receive"whileTrue:
message, clientAddress=serverSocket.recvfrom(2048)
print'Received from %s:%s.'%clientAddressprint'Message: %s'%messagemodifiedMessage=message.upper()
serverSocket.sendto(modifiedMessage, clientAddress)
ifmessagein ['exit', 'quit']:
print'Bye!'breakserverSocket.close()
print'Connection from %s:%s closed.'%clientAddress
套接字有唯一标识符,每个报文段有特殊字符来指示该报文段所要交付到的套接字。这些特殊字段是源端口号字段(source port number field)和目的端口号字段(destination port number field)。端口号是一个16比特的数,其大小在 065535 之间。01023 范围的端口号称为周知端口号(well-known port number)。
Acknowledgement Number 就是确认号 ACK,用于确认收到,用来解决丢包的问题。
Window,接受窗口字段,用于流量控制。
TCP Flag ,也就是包的类型,主要是用于操控 TCP 的状态机。
三次握手和四次挥手
三次握手
第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为1,Sequence Number 为 x;然后,客户端进入 SYN_SEND 状态,等待服务器的确认;
第二次握手:服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为 x+1 (Sequence Number+1);同时,自己还要发送 SYN 请求信息,将 SYN 位置为1,Sequence Number 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 报文段。然后将 Acknowledgment Number 设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。完成了三次握手,客户端和服务器端就可以开始传送数据。
四次挥手
第一次挥手:主机1(可以使客户端,也可以是服务器端),设置 Sequence Number 和 Acknowledgment Number,向主机2发送一个 FIN 报文段;此时,主机1进入 FIN_WAIT_1 状态;这表示主机1没有数据要发送给主机2了;
第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回一个 ACK 报文段,Acknowledgment Number 为Sequence Number 加1;主机1进入 FIN_WAIT_2 状态;主机2告诉主机1,我“同意”你的关闭请求;
第三次挥手:主机2向主机1发送 FIN 报文段,请求关闭连接,同时主机2进入 LAST_ACK 状态;
第四次挥手:主机1收到主机2发送的 FIN 报文段,向主机2发送ACK报文段,然后主机1进入 TIME_WAIT 状态;主机2收到主机1的 ACK 报文段以后,就关闭连接;此时,主机1等待2 MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机1也可以关闭连接了。
client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。”
计算机网络和因特网
概述
因特网是一个世界范围的计算机网络,即它是一个互联了遍及全世界的数以亿计的计算机设备的网络。所有这些设备都称为主机(host)或端系统(end system)。
端系统通过通信链路(communication link)和分组交换机(packet switch)连接到一起。
不同的链路(同轴电缆,铜线,光纤和无线电频谱)能够以不同的速率传输数据,链路的传输速率以比特/秒度量(bit/s 或 bps)。当一台端系统要向另一台端系统发送数据时,发送端系统将数据分段,并为每段加上首部字节。由此形成的信息包被称为分组(packet)。这些分组通过网络发送到目的端系统,在那里被装配为初始数据。
分组交换机从它的一条入通信链路接受到达的分组,并从它的一条出通信链路转发该分组。分组交换机两种最著名的类型是路由器(router)和链路层交换机(link-layer switch)。链路层交换机通常用于接入网中,而路由器通常用于网络核心中。
网络核心
分组交换
在各种网络应用中,端系统彼此交换报文(message)。报文可以执行一种控制功能,也可以包含数据。为了从源端系统向目的端系统发送一个报文,源将长报文划分为较小的数据块,称之为分组(packet)。在源和目的之间,每个分组都通过通信链路和分组交换机传送。
电路交换
传统的电话网络是电路交换
链路中的电路是通过频分复用(Frequency-Division Multiplexing,FDM)或时分复用(Time-Division Multiplexng,TDM)来实现的。
协议层次
应用层
概述
应用层是网络应用程序及它们的应用层协议存留的地方。
应用层协议分布在多个端系统上,一个端系统中的应用程序使用协议与另一个端系统中的应用程序交换信息的分组。我们把这种位于应用层的信息分组称为报文(message)
HTTP
HTTP概况
Web 的应用层协议是超文本传输协议(HyperText Transfer Protocol,HTTP),它是Web的核心,在[RFC 1945] 和 [RFC 2616] 中进行了定义。HTTP由两个程序实现:一个客户端程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP定义了这些报文的结构以及客户和服务器进行报文交换的方式。
HTTP使用TCP作为它的支撑运输协议。HTTP客户首先发起一个与服务器的TCP连接。一旦连接建立,该浏览器和服务器进程就可以通过套接字接口访问TCP。客户端的套接字接口是客户进程与TCP连接之间的门,在服务器端的套接字接口则是服务器进程与TCP连接之间的门。客户向它的套接字接口发送HTTP请求报文并从它的套接字接口接受HTTP响应报文。类似地,服务器从它的套接字接口接受HTTP请求报文和向它的套接字接口发送HTTP响应报文。一旦客户向它的套接字接口发送了一个请求报文,该报文就脱离了客户控制并进入TCP的控制。
TCP为HTTP提供可靠数据传输服务。这意味着,一个客户进程发出的每个HTTP请求报文最终能完整地到达服务器。类似地,服务器进程发出的每个HTTP响应报文最终能完整地到达客户。
HTTP是一个无状态协议(stateless protocol)
非持续连接和持续连接
每个请求/响应对是经过一个单独的TCP连接发送称为非持续连接(non-persistent connection)。
所有的请求/响应对经相同的TCP连接发送称为持续连接(persistent connection)。
在 HTTP 1.0 中, 没有官方的 keepalive 的操作。通常是在现有协议上添加一个指数。如果浏览器支持 keep-alive,它会在请求的包头中添加:
然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中:
这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端认为会话已经结束,其中一方中断连接。
在 HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。HTTP 持久连接不使用独立的 keepalive 信息,而是仅仅允许多个请求使用单个连接。然而, Apache 2.0 httpd 的默认连接过期时间是仅仅15秒 ,对于 Apache 2.2 只有5秒。短的过期时间的优点是能够快速的传输多个web页组件,而不会绑定多个服务器进程或线程太长时间。
HTTP请求报文
客户端请求:
(末尾有一个空行。第一行指定方法、资源路径、协议版本;第二行是在1.1版里必带的一个header作用指定主机)
服务器应答:
(紧跟着一个空行,并且由HTML格式的文本组成了Google的主页)
在HTTP1.0,单一TCP连接内仅执行一个“客户端发送请求—服务器发送应答”周期,之后释放TCP连接。在HTTP1.1优化支持持续活跃连接:客户端连续多次发送请求、接收应答;批量多请求时,同一TCP连接在活跃(Keep-Live)间期内复用,避免重复TCP初始握手活动,减少网络负荷和响应周期。此外支持应答到达前继续发送请求(通常是两个),称为“流线化”(stream)。
管线化
HTTP管线化(HTTP pipelining)是将多个 HTTP 请求整批提交的技术,而在发送过程中不需先等待服务端的回应。见 RFC 2616 Connections
Cookie
Cookie 在 RFC 6265 中定义,通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。
FTP
文件传输协议(File Transfer Protocol)是用于在[网络上进行文件传输的一套标准协议,使用客户/服务器模式。它属于网络传输协议的应用层。RFC 959 定义了此规范。
DNS
P2P
SSH
SSH是一种网络协议,用于计算机之间的加密登录。
在客户端来看,SSH提供两种级别的安全验证。
TCP套接字编程
TCPClient
TCPServer
UDP套接字编程
UDPClient
UDPServer
运输层
概述
运输层协议为运行在不同主机上的应用程序之间提供了逻辑通信(logic communication)功能。从应用程序的角度看,通过逻辑通信,运行不同进程的主机好像直接相连一样,实际上,这些主机也许位于地球的两侧,通过很多路由器及多种不同类型的链路相连。
运输层协议是在端系统中而不是路由器中实现的。在发送端,运输层将从发送发送应用程序进程接收到的报文转换成运输层分组,该分组被称为运输层报文段(segment)。实现的方法可能是将应用报文划分为较小的块,并为每块加上一个运输层首部以生成运输层报文段。然后,在发送端系统中,运输层将这些报文段传递给网络层,网络层再将其封装成网络层分组(即数据报)并向目的地发送。
多路复用与多路分解
一个进程有一个或多个套接字(socket),它相当于从网络向进程传递数据和从进程向网络传递数据的门户。每个套接字都有唯一的标识符。标识符的格式取决于它是 UDP 还是 TCP 套接字。
将运输层报文段中的数据交付到正确的套接字的工作称为多路分解(demultiplexing)。在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,这些工作被称为多路复用(multiplexing)
套接字有唯一标识符,每个报文段有特殊字符来指示该报文段所要交付到的套接字。这些特殊字段是源端口号字段(source port number field)和目的端口号字段(destination port number field)。端口号是一个16比特的数,其大小在 0
65535 之间。01023 范围的端口号称为周知端口号(well-known port number)。UDP
用户数据报协议(User Datagram Protocol,UDP),是一个简单的面向数据报的传输层协议,正式规范为 RFC 768。
UDP 只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份,此外,传输途中即使出现丢包,UDP 也不负责重发,所以UDP有时候也被认为是不可靠的数据报协议。UDP 在 IP 数据报的头部仅仅加入了复用和数据校验。
报文段结构
对于 DNS 应用,数据字段要么包含一个查询报文,要么包含一个响应报文。对于流式音频应用,音频抽样数据填充到数据字段。
UDP 校验和提供了差错检测功能。这就是说,校验和用于确认当 UDP 报文段从源到达目的地移动时,其中的比特是否发生了变化(链路中的噪声干扰或者存储在路由器中时引入问题)。
可靠数据传输原理
数据可以通过一条可靠的信道进行传输。借助于可靠信道,传输数据比特就不会受到损坏(0变成1 或者 1变成0)或丢失,而且所有数据都是按照其发送顺序进行交付。实现这种服务抽象是可靠数据传输协议(reliable data transfer protocol)的责任。
TCP
传输控制协议(Transmission Control Protocol,TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的 RFC 793 定义。
TCP报文段首部
三次握手和四次挥手
三次握手
第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为1,Sequence Number 为 x;然后,客户端进入 SYN_SEND 状态,等待服务器的确认;
第二次握手:服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为 x+1 (Sequence Number+1);同时,自己还要发送 SYN 请求信息,将 SYN 位置为1,Sequence Number 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 报文段。然后将 Acknowledgment Number 设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。完成了三次握手,客户端和服务器端就可以开始传送数据。
四次挥手
第一次挥手:主机1(可以使客户端,也可以是服务器端),设置 Sequence Number 和 Acknowledgment Number,向主机2发送一个 FIN 报文段;此时,主机1进入 FIN_WAIT_1 状态;这表示主机1没有数据要发送给主机2了;
第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回一个 ACK 报文段,Acknowledgment Number 为Sequence Number 加1;主机1进入 FIN_WAIT_2 状态;主机2告诉主机1,我“同意”你的关闭请求;
第三次挥手:主机2向主机1发送 FIN 报文段,请求关闭连接,同时主机2进入 LAST_ACK 状态;
第四次挥手:主机1收到主机2发送的 FIN 报文段,向主机2发送ACK报文段,然后主机1进入 TIME_WAIT 状态;主机2收到主机1的 ACK 报文段以后,就关闭连接;此时,主机1等待2 MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机1也可以关闭连接了。
TCP 流量控制
一般来说,我们希望数据传输的更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接受,这就会造成数据的丢失。所谓流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接受。
利用滑动窗口机制可以在 TCP 连接上实现对发送方的流量控制。
发送方的发送窗口不能超过接收方给出的接受窗口的数值。
TCP 拥塞控制
网络中的链路容量(带宽),交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫做拥塞(congestion)。
所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
拥塞控制是一个全局性的过程,涉及到所有的主机,路由器以及与降低网络传输性能有关的所有因素。相反,流量控制往往指点对点通信量的控制,是一个端到端的问题(接收端控制发送端)。流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接受
拥塞控制方法
RFC 2581 定义了拥塞控制的四种算法,即慢开始(slow-start),拥塞避免(congestion avoidance),快重传(fast retransmit)和快恢复(fast recovery)。
慢开始和拥塞避免
发送方维持一个叫做拥塞窗口 cwnd (congestion window) 的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。
发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。所以较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。
快重传和快恢复
快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等待自己发送数据时才进行捎带确认。
The text was updated successfully, but these errors were encountered: