【网络基础】 TCP & UDP 基础

TCP报文格式


  • source发送TCP数据的源端口
  • dest接受TCP数据的目的端口
  • seq标识该TCP所包含的数据字节的开始序列号
  • ack_seq确认序列号,表示接受方下一次接受的数据序列号。
  • doff数据首部长度。和IP协议一样,以4字节为单位。一般的时候为5
  • urg如果设置紧急数据指针,则该位为1
  • ack如果确认号正确,那么为1
  • psh如果设置为1,那么接收方收到数据后,立即交给上一层程序
  • rst为1的时候,表示请求重新连接
  • syn为1的时候,表示请求建立连接
  • fin为1的时候,表示请求关闭连接window窗口,告诉接收者可以接收的大小check对TCP数据进行较核
  • urg_ptr如果urg=1,那么指出紧急数据对于历史数据开始的序列号的偏移值

TCP连接建立三次握手

  • 第一次握手:建立连接时,客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
  • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
  • 完成三次握手,客户端与服务器开始传送数据,

TCP优缺点

优点

  • TCP提供以认可的方式显式地创建和终止连接。
  • TCP保证可靠的、顺序的(数据包以发送的顺序接收)以及不会重复的数据传输。
  • TCP通过保持连续并将数据块分成更小的分片来处理大数据块。无需程序员知道

缺点

  • TCP在传递数据时必须创建(并保持)一个连接。这个连接给通信进程增加了开销,让它比UDP速度要慢。TCP 连接的资源消耗,其中包括:数据包信息、条件状态、序列号等。
  • TCP连接存在安全隐患:通过故意不完成建立连接所需要的三次握手过程,造成连接一方的资源耗尽
  • 序列号的可预测性,目标主机应答连接请求时返回的SYN/ACK 的序列号是可预测的 TCP 会话劫持和SYN FLOOD(同步洪流)就是根据TCP的这个弱点出现的一种网络攻击方式

TCP 数据结构

在TCP连接建立的过程中,会用到一些数据结构

  • 半连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN 包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
  • Backlog参数:表示未连接队列的最大容纳数目。
  • SYN-ACK 重传次数:服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
  • 半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间

TCP 标志位

应该就是code bit那个字段的位的意义

  • SYN(同步标志):该标志置上的时候,同步序列编号(Synchronize Sequence Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。  
  • ACK(确认标志):该标志置上的时候,确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。  
  • RST(复位标志):该标志置上的时候,用于复位相应的TCP连接。
  • URG(紧急标志):该标志置上的时候,表示紧急(The urgent pointer) 标志有效。
  • PSH(推标志):该标志置位时,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的。  
  • FIN(结束标志):带有该标志置位的数据包用来结束一个TCP回话,但对应端口仍处于开放状态,准备接收后续数据。

TCP连接过程的中间状态

  • SYN_SENT:客户端发送syn数据包向服务器端申请建立TCP连接,此时客户端的状态为SYN_SENT
  • SYN_RCVD:接收方收到请求,给发起方发送一个设置了SYN与ACK标志位的TCP数据包做为应答,另外设置一个比客户机发送来的ISN大1个单位的ISN值,这常被称为SYN_ACK数据包或SYN_ACK报文这时连接的状态称做SYN_RCVD
  • ESTABLISHED:发起方然后发送一个带有ACK应答和增1后的ISN标志来确认SYN_ACK至此,完成了三次握手,此时的连接状态为连结成功: ESTABLISHED

TCP连接终止协议(四次挥手)

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。
服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。
客户段发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。


关闭连接等待两倍最大生存时间

主动关闭连接方发送ack响应后,为什么需要等待两倍最大生存时间后再关闭连接?

因为主动方发送的ACK消息可能丢失,并导致被动方再次发送FIN报文,TIME_WAIT为连接中”离群的段”提供从网络中消失的时间。考虑一下,如果延迟或者重传段在连接关闭后到达时会发生什么呢?通常情况下,因为TCP仅仅丢弃该数据并响应RST消息,所以这不会造成任何问题。当RST消息到达发出延时段的主机时,因为该主机也没有记录连接的任何信息,所以它也丢弃该段。然而,如果两个相同主机之间又建立了一个具有相同端口号的新连接,那么离群的段就可能被看成是新连接的,如果离群的段中数据的任何序列号恰恰在新连接的当前接收窗口中,数据就会被重新接收,其结果就是破坏新连接

  • 简单点说:就是为了将之前的TCP连接的端口号给占住,不让新的TCP连接使用,避免之前TCP连接上发出的包(因为某些原因比较晚才到达目标主机)被新的TCP连接给收到和处理。

TCP关闭连接时状态

  • CLOSED: 初始状态。
  • LISTEN: 服务器端的某个SOCKET处于监听状态,可以接受连接了
  • FIN_WAIT_1:FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
  • FIN_WAIT_2:FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
  • TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL(2倍最大生存时间)后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
  • CLOSING: 正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
  • CLOSE_WAIT: 在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
  • LAST_ACK: 它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

三次和四次

为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。


TCP Socket 编程流程图


UDP socket 编程流程图


UDP和TCP区别

  • UDP没有三次握手过程。
  • UDP处理的细节比TCP少。UDP不能保证消息被传送到(它也报告消息没有传送到)目的地。
  • UDP也不保证数据包的传送顺序。UDP把数据发出去后只能希望它能够抵达目的地。

UDP优缺点:

  • UDP不要求保持一个连接
  • UDP没有因接收方认可收到数据包(或者当数据包没有正确抵达而自动重传)而带来的开销。
  • 设计UDP的目的是用于短应用和控制消息
  • 在一个数据包连接一个数据包的基础上,UDP要求的网络带宽比TDP更小。

Socket概念

  • 网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符
  • Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

Socket类型

  • 流式Socket(SOCK_STREAM):流式是一种面向连接的Socket,针对于面向连接的TCP服务应用
  • 数据报式Socket(SOCK_DGRAM):数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用

socket调用库函数主要有:

下面这几个接口都会创建一个socket

  • Socket(af,type,protocol):创建套接字
  • bind(sockid, local addr, addrlen):建立地址和套接字的联系
  • listen( Sockid ,quenlen):服务器端侦听客户端的请求


建立服务器/客户端的连接 (面向连接TCP)

  • Connect(sockid, destaddr, addrlen) :客户端请求连接
  • newsockid=accept(Sockid,Clientaddr, paddrlen):服务器端等待从编号为Sockid的Socket上接收客户连接请求


发送/接收数据

  • send(sockid, buff, bufflen) :面向连接的发送数据
  • recv( ) :面向连接的接收数据
  • sendto(sockid,buff,…,addrlen) 面向无连接发送数据
  • recvfrom( )面向无连接的接收数据

释放套接字

  • close(sockid)

【网络基础】 TCP & UDP 基础

时间: 2024-11-12 09:10:16

【网络基础】 TCP & UDP 基础的相关文章

Photon服务器引擎(二)socket/TCP/UDP基础及Unity聊天室的实现

Photon服务器引擎(二)socket/TCP/UDP基础及Unity聊天室的实现 我们平时说的最多的socket是什么呢,实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API). 通过Socket,我们才能使用TCP/IP协议.实际上,Socket跟TCP/IP协议没有必然的联系.Socket编程接口在设计的时候,就希望也能适应其他的网络协议.所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,

python 网络通信协议/TCP,UDP区别

一.osi七层协议 互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层 协议具体内容 各层的功能简述: [1]物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后在转化为1.0,也就是我们常说的数模转换与模数转换),这一层的数据叫做比特. [2]数据链路层:定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问,这一层通常还提供错误检测和纠正,以确保数

第二十七天- 网络通信协议 TCP UDP 缓冲区

1.网络通信协议 osi七层模型:按照分工不同把互联网协议从逻辑上划分了层级 socket层 2.理解socket: Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议.我们可理解成模块,直接拿来用. 套接字socket历史: 套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本

python 学习5 网络编程-TCP/UDP

摘抄自:廖雪峰的官方网站:http://www.liaoxuefeng.com/ TCP客户端和服务器端代码: #coding=utf-8 #客户端程序TCP 连接 import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('127.0.0.1',9999)) print(s.recv(1024)) for data in ['Michael','Tracy','Sarah']: s.send(data

linux网络编程--tcp/udp编程模型

tcp 模型如下: 上面的模型已经很清楚了 具体函数用法就不细说了 请看tcp简单的例子: 其中server.c #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h> #define e

异常处理与网络基础中的tcp,udp协议

# 异常处理: # 什么是异常?异常和错误的区别 # Error 语法错误 比较明显的错误 在编译代码阶段就能检测出来 # Iteration 异常 在执行代码的过程中引发的异常 # 异常发生之后的效果 # 一旦在程序中发生异常,程序就不再继续执行了 # try: # # name # [][3] # except NameError: # print("请设置好变量!!") # except IndexError: #分支异常处理 # print('请认真!!') # # excep

网络编程—网络基础概览、socket,TCP/UDP协议

网络基础概览 socket概览 socket模块-TCP/UDP的实现 TCP/UDP总结 网络基础概览 osi七层协议各层主要的协议 # 物理层传输电信号1010101010 # 数据链路层,以太网协议,arp协议.对这些信号进行分组,同时规范了分组形式--以太网协议,头部是mac地址中间是信息, # 网络层:ip协议,arp协议帮忙找到mac地址,ip,子网掩码,网关(下面有一些简单概括) # 传输层:tcp协议,udp协议 # (socket)就是一组接口,将复杂的tcp协议和udp协议隐

网络基础---TCP/IP五层模型

网络基础---TCP/IP五层模型 计算机之间的通讯是通过互联网来进行的,各个计算机在internet上遵循它的一系列协议才能进行通讯,因此实际上可以把互联网本质看作是一系列的网络协议. 1.TCP/IP五层模型 (1)物理层功能:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0 (2)数据链路层的功能:建立逻辑连接.进行硬件地址寻址.差错校验等功能(由底层网络定义协议).并且将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正. 1)以广播的方式通

JAVA基础学习day24--Socket基础一UDP与TCP的基本使用

一.网络模型 1.1.OIS参考模型 1.2.TCP/IP参考模型 1.3.网络通讯要素 IP地址:IPV4/IPV6 端口号:0-65535,一般0-1024,都被系统占用,mysql:3306,oracle:1521 传输协议:TCP/UDP 二.类 InetAddress 2.1.InetAddress 主机对象 IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的 2.2.示例 import java.net.*;