初入网络系列笔记(2)TCP和UDP

一、借鉴说明,本博文借鉴以下博文

  1.BlueTzar,TCP/IP四层模型,
http://www.cnblogs.com/BlueTzar/articles/811160.html

  2.叶剑峰,漫谈TCP,
http://www.cnblogs.com/yjf512/p/5909031.html

  3.bizhu,TCP和UDP的区别(转),
http://www.cnblogs.com/bizhu/archive/2012/05/12/2497493.html

  4.任智康,TCP/IP、Http的区别,
http://www.cnblogs.com/renyuan/archive/2013/01/19/2867720.html

二、TCP和UDP

  • 基础知识

  1.TCP

  TCP是一种可靠的、面向连接的字节流服务。源主机在传送数据前需要先和目标主机建立连接。然后,在此连接上,被编号的数据段按序收发。同时,要求对每个数据段进行确认,保证了可靠性。如果在指定的时间内没有收到目标主机对所发数据段的确认,源主机将再次发送该数据段。如图所示,是TCP的数据报格式。

  ●源、目标端口号字段:占16比特。TCP协议通过使用"端口"来标识源端和目标端的应用进程。端口号可以使用0到65535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在"众所周知的端口"(Well-Know Port)为用户提供服务。

  ●序列号字段:占32比特。用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。

●确认号字段:占32比特。只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节。

  ●首部长度字段:占4比特。给出头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。

  ●标志位字段(U、A、P、R、S、F):占6比特。各比特的含义如下:

  ◆URG:紧急指针(urgent pointer)有效。

  ◆ACK:确认序号有效。

  ◆PSH:接收方应该尽快将这个报文段交给应用层。

  ◆RST:重建连接。

  ◆SYN:发起一个连接。

  ◆FIN:释放一个连接。

  ●窗口大小字段:占16比特。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。

  ●TCP校验和字段:占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。

  ●紧急指针字段:占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。

●选项字段:占32比特。可能包括"窗口扩大因子"、"时间戳"等选项。

滑动窗口

  滑动窗口是接收端告诉发送端下次可以发送多少包。好吧,这里也需要面对几个问题:

  避免误区:发送方和接受方的请求-响应并不是一一对应的。

  网络上并不是只有发送方发一个请求,接收方回复一个ACK这种模式的。他们交互的模式更可能是:发送方一次发送多个请求包,接收方回复一个ACK,把这些请求包都回复了。这个使用前面的Acknowledgment Number是可以做到的。

  但是基本上,在接收方的角度,ACK包一定是收到一个包之后,才返回一个ACK,就是说,没有无缘无故的发送重复ACK,没有一个请求,多个ACK这种情况。但是有多个请求,多个重复ACK的情况,这个时候,往往说明某个请求的包丢失了。

  为什么需要有滑动窗口存在?

  滑动窗口的存在是为了控制网络上包的数量。如果没有滑动窗口,那么就是一个很理想很理想的情况,发送方一有数据,加上包头达到MTU大小,直接发送,就和冲锋枪一样,突突突突。但是呢?这样子,实际上,没有考虑到接收方是否能接收完。接收端就像一个一直在吃饭的胖子,他的吃饭速度是固定的,它一次性最多能吃10碗饭,某个时刻可能已经吃了两碗饭,但是还没消化。所以这个时候,它只能再吃8碗饭了,如果这个时候你一下子给它80碗,必然导致它堵死了,吃不下不吃下。这个滑动窗口就是接收端告诉发送端我还能吃几碗饭的通话器。滑动窗口,限制发送方一次发送的包数量。

  为什么叫滑动窗口?

  滑动窗口我更愿意理解为发送方和接收方共同维护的。分别有发送窗口和接收窗口区别。

发送方数据有几个状态:数据已发送未收到ACK,数据已发送收到ACK

  接收方数据有几个状态:数据已收到未被应用层消费,数据已收到已被应用层消费

  把发送数据横拍做长列状,发送方一旦有数据收到ACK,那么滑动窗口左侧边就进行左移。同样,一旦接收方有数据被应用层消费,那么,滑动窗口的右侧边就进行右移。整个过程,就好比努力爬行的蚯蚓,尾巴向前挪一寸,头部再向前走一寸,直到把整个数据都从头到尾移动完毕。

  回到TCP的滑动窗口字段,这个字段是接收端回复给发送端,告诉发送端接收端的窗口大小的。我们其实默认也把这个窗口大小叫做滑动窗口大小。

  关于滑动窗口的概念的理解,我的感触是网上各种各样对这个滑动窗口的描述,不要陷入到咬文嚼字中,头脑中形象有这个滑动窗口的滑动过程,就可以了,很多文章很多描述可能是前后矛盾的。比如,下面两个关于发送窗口的描述:

  • 发送窗口是由滑动窗口和拥塞窗口共同决定的。
  • 发送窗口是由接收窗口决定的。

建立连接和释放连接

TCP著名的三次握手和四次挥手

这个图里面的client和server应该理解为发送方和接收方。下面这一串描述请熟练练习到像串口相声一样:发送方发送一个SYN到接收方请求建立连接,接收方返回一个ACK确认收到请求,并携带一个SYN给发送方请求建立双向连接,发送方再返回一个ACK给接收方确认,这个时候连接就建立了。

顺势说下四次挥手吧。发送方发送一个FIN给接收方主动请求断开连接,接收方返回一个ACK确认,接着接收方再发送一个FIN请求断开另一方向的连接,发送方收到之后返回一个ACK确认。这个时候,连接就中断了。

  2.UDP

  UDP是一种不可靠的、无连接的数据报服务。源主机在传送数据前不需要和目标主机建立连接。数据被冠以源、目标端口号等UDP报头字段后直接发往目的主机。这时,每个数据段的可靠性依靠上层协议来保证。在传送数据较少、较小的情况下,UDP比TCP更加高效。如图所示,是UDP的数据报结构。

 

  ●源、目标端口号字段:占16比特。作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程。

  ●长度字段:占16比特。标明UDP头部和UDP数据的总长度字节。

●校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。

  • 相关知识:套接字

  在每个TCP、UDP数据段中都包含源端口和目标端口字段。有时,我们把一个IP地址和一个端口号合称为一个套接字(Socket),而一个套接字对(Socket pair)可以唯一地确定互连网络中每个TCP连接的双方(客户IP地址、客户端口号、服务器IP地址、服务器端口号)。如图所示,是套接字的示意图。

  需要注意的是,不同的应用层协议可能基于不同的传输层协议,如FTP、TELNET、SMTP协议基于可靠的TCP协议。TFTP、SNMP、RIP基于不可靠的UDP协议。

  同时,有些应用层协议占用了两个不同的端口号,如FTP的20、21端口,SNMP的161、162端口。这些应用层协议在不同的端口提供不同的功能。如FTP的21端口用来侦听用户的连接请求,而20端口用来传送用户的文件数据。再如,SNMP的161端口用于SNMP管理进程获取SNMP代理的数据,而162端口用于SNMP代理主动向SNMP管理进程发送数据。

  还有一些协议使用了传输层的不同协议提供的服务。如DNS协议同时使用了TCP 53端口和UDP 53端口。DNS协议在UDP的53端口提供域名解析服务,在TCP的53端口提供DNS区域文件传输服务。

时间: 2024-10-04 21:07:43

初入网络系列笔记(2)TCP和UDP的相关文章

初入网络系列笔记(4)HTTP请求和响应

一.借鉴说明,本博文借鉴以下博文 1.starok,HTTP必知必会,http://www.cnblogs.com/starstone/p/4890409.html 2.CareySon,HTTP协议漫谈,http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html 3.逖靖寒,浅析HTTP协议,http://www.cnblogs.com/gpcuster/archive/2009/05/25/1488749.htm

初入网络系列笔记(3)HTTP协议最简单的掌握

一.借鉴说明,本博文借鉴以下博文 1.starok,HTTP必知必会,http://www.cnblogs.com/starstone/p/4890409.html 2.CareySon,HTTP协议漫谈,http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html 3.逖靖寒,浅析HTTP协议,http://www.cnblogs.com/gpcuster/archive/2009/05/25/1488749.htm

UNIX网络编程笔记(6)—UDP网络编程

基本UDP套接字编程 1. 概述 TCP和UDP的本质区别就在于:UDP是无连接不可靠的数据报协议,TCP是面向连接的可靠字节流.因此使用TCP和UDP编写的应用程序存在一些差异.使用UDP编写的一些常见的应用程序有:DNS(域名解析系统).NFS(网络文件系统)和SNMP(简单网络管理协议). 2. sendto和recvfrom函数 类似与标准的read和write函数: #include <sys/socket.h> ssize_t recvfrom (int sockfd,void *

Linux网络编程8&mdash;&mdash;对TCP与UDP的简易封装

引言 每次使用socket通信,都会有很对相似的操作.本文,会对TCP与UDP通信做一简单封装,并生成动态库. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #define __MY_SOCKET_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #in

python网络编程(通过tcp或者udp协议通信)

1.基于tcp协议传送文件: 客户端: import socketimport osimport jsonimport structclient = socket.socket()client.connect(('127.0.0.1',8080)) # 文件大小file_size = os.path.getsize(r'F:\老男孩Python7期\day32\视频\02TCP发送大文件.mp4') # 文件名字file_name = 'TCP发送大文件.mp4'# 定义一个字典d = { 'f

Linux网络编程9&mdash;&mdash;对TCP与UDP的简易封装2.0

具体生成动态库的操作及使用该动态库的操作请参见上篇博文.以下仅仅列出改进版本的代码. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #define __MY_SOCKET_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys

从零探索Java网络编程01之 TCP/IP 与 Socket

最近完成了几项比较简单的项目, 日子有些松散, 终于是在996里偷了点闲暇时光, 想着来研究研究些啥吧?  一个普通的控制台日志映入了我的眼帘(孽缘呀): (图中使用 SpringBoot 的 log4j 来输出日志, logginglevel: debug, jdk版本为1.8) 造成这种现象的原因可能是, Mybatis在执行接口方法时, 实例化了多个Preparedstatement, 启用了不同的NIO线程, 但是其中, 咦?! 没错, NIO中出了一段IO!!! (天哪!), 在查询网

TCP和UDP的&quot;保护消息边界”

转自:http://blog.csdn.net/zhangxinrun/article/details/6721427 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包.这样,接收端,就难于分辨出来了,必须提供科学的拆包机制.    

【转】关于TCP和UDP协议消息保护边界的介绍

在 socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包.这样,接收端,就难于分辨出来了,必须提供科学的拆包机制.对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接