ethermet socket
TCP/UDP
TCP保证可靠性
- 序列号、确认应答、超时重传
- 数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明它下一次需要接收的数据序列号。如果发送方迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。这个时间一般是2*RTT(报文段往返时间)+一个偏差值
- 窗口控制与高速重发控制/快速重传(重复确认应答)
- TCP会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值。如果不使用窗口控制,每一个没收到确认应答的数据都要重发。使用窗口控制,如果数据段1001-2000丢失,后面数据每次传输,确认应答都会不停地发送序号为1001的应答,表示我要接收1001开始的数据,发送端如果收到3次相同应答,就会立刻进行重发;但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒…
TCP 三次握手建立连接(Three-way Handshake)
TCP 连接的建立需要经过三次握手,确保客户端和服务器双方都具备发送和接收数据的能力。过程如下:
第一次握手:客户端发送 SYN
- 客户端向服务器发送一个带 SYN 标志位的数据包(SYN=1,Seq=x),表示请求建立连接。
- 此时客户端进入 SYN_SEND 状态。
第二次握手:服务器应答 SYN+ACK
- 服务器收到 SYN 包后,确认客户端的 SYN(ACK=1,Ack=x+1),同时自己也发送一个 SYN 包(SYN=1,Seq=y)。
- 服务器将 SYN 和 ACK 一起发送(SYN=1,ACK=1,Seq=y,Ack=x+1)。
- 服务器进入 SYN_RCVD 状态。
第三次握手:客户端确认 ACK
- 客户端收到服务器的 SYN+ACK 包后,发送一个确认包(ACK=1,Seq=x+1,Ack=y+1)给服务器。
- 客户端进入 ESTABLISHED 状态,服务器收到后也进入 ESTABLISHED 状态,连接建立完成。
说明
- 三次握手的目的是同步双方的初始序列号(Seq),并确认双方的接收能力。
- 若握手过程中某一步失败,连接不会建立,需重新发起。
- 握手完成后,双方可以开始可靠的数据传输。
TCP 四次挥手断开连接(Four-way Handshake)
TCP 连接的断开需要经过四次挥手,确保双方都能完成数据传输并正常释放资源。过程如下:
第一次挥手:客户端发送 FIN
- 客户端向服务器发送一个带 FIN 标志位的数据包(FIN=1,Seq=u),表示客户端没有数据要发送了,请求关闭连接。
- 客户端进入 FIN_WAIT_1 状态。
第二次挥手:服务器应答 ACK
- 服务器收到 FIN 包后,发送一个确认包(ACK=1,Ack=u+1,Seq=v)给客户端,表示已收到关闭请求。
- 服务器进入 CLOSE_WAIT 状态,客户端收到 ACK 后进入 FIN_WAIT_2 状态。
第三次挥手:服务器发送 FIN
- 服务器处理完剩余数据后,向客户端发送一个带 FIN 标志位的数据包(FIN=1,Seq=w),请求关闭连接。
- 服务器进入 LAST_ACK 状态。
第四次挥手:客户端应答 ACK
- 客户端收到服务器的 FIN 包后,发送一个确认包(ACK=1,Ack=w+1)给服务器。
- 客户端进入 TIME_WAIT 状态,等待一段时间后彻底关闭连接;服务器收到 ACK 后立即关闭连接,进入 CLOSED 状态。

tcp三次握手和四次挥手的原因
为什么是三次握手?
- 为了防止已失效的连接请求报文段突然有送到了B,因而产生错误
- 假设两次握手时,A发出的第一个请求连接报文段在某一网络节点长时间滞留,以致延误到连接释放后才到达B。B收到失效的连接请求报文段后,认为是A又发出一次新的连接请求。于是向A发送确认报文段,同意建立连接,此时在假定两次握手的前提下,连接建立成功。这样会导致B的资源白白浪费
- 假设两次握手时,A发出一个请求报文段,但发送过后A就因为问题而导致下线。之后B收到了A发来的请求连接报文段,给A发送确认报文段,同意建立连接,此时在假定两次握手的前提下,连接建立成功。这样会导致B的资源白白浪费
为什么是四次挥手?
- TCP协议是全双工通信,这意味着客户端和服务器端都可以向彼此发送数据,所以关闭连接是双方都需要确认的共同行为
- 假设是三次挥手时,首先释放了A到B方向的连接,此时TCP连接处于半关闭(Half-Close)状态,这时A不能向B发送数据,而B还是可以向A发送数据。如果此时A收到了B的确认报文段后,就立即发送一个确认报文段,这会导致B向A还在发送数据时连接就被关闭。这样会导致A没有完整收到B所发的报文段
TCP状态变迁(状态机)

time_wait
首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就说该发送方会保持2MSL时间之后才会回到初始状态。MSL指的是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。
- 为实现TCP全双工连接的可靠释放
由TCP状态变迁图可知,假设发起主动关闭的一方(client)最后发送的ACK在网络中丢失,由于TCP协议的重传机制,执行被动关闭的一方(server)将会重发其FIN,在该FIN到达client之前,client必须维护这条连接状态,也就说这条TCP连接所对应的资源(client方的local_ip,local_port)不能被立即释放或重新分配,直到另一方重发的FIN达到之后,client重发ACK后,经过2MSL时间周期没有再收到另一方的FIN之后,该TCP连接才能恢复初始的CLOSED状态。如果主动关闭一方不维护这样一个TIME_WAIT状态,那么当被动关闭一方重发的FIN到达时,主动关闭一方的TCP传输层会用RST包响应对方,这会被对方认为是有错误发生,然而这事实上只是正常的关闭连接过程,并非异常。 - 为使旧的数据包在网络因过期而消失
先假设TCP协议中不存在TIME_WAIT状态的限制,再假设当前有一条TCP连接:(local_ip, local_port, remote_ip,remote_port),因某些原因,我们先关闭,接着很快以相同的四元组建立一条新连接。TCP连接由四元组唯一标识,因此,在我们假设的情况中,TCP协议栈是无法区分前后两条TCP连接的不同的,在它看来,这根本就是同一条连接,中间先释放再建立的过程对其来说是“感知”不到的。这样就可能发生这样的情况:前一条TCP连接由local peer发送的数据到达remote peer后,会被该remot peer的TCP传输层当做当前TCP连接的正常数据接收并向上传递至应用层(而事实上,在假设的场景下,这些旧数据到达remote peer前,旧连接已断开且一条由相同四元组构成的新TCP连接已建立,因此,这些旧数据是不应该被向上传递至应用层的),从而引起数据错乱进而导致各种无法预知的诡异现象。作为一种可靠的传输协议,TCP必须在协议层面考虑并避免这种情况的发生,这正是TIME_WAIT状态存在的第2个原因。
具体而言,local peer主动调用close后,此时的TCP连接进入TIME_WAIT状态,处于该状态下的TCP连接不能立即以同样的四元组建立新连接,即发起active close的那方占用的local port在TIME_WAIT期间不能再被重新分配。由于 TIME_WAIT状态持续时间为2MSL,这样保证了旧TCP连接双工链路中的旧数据包均因过期(超过MSL)而消失,此后,就可以用相同的四元组建立一条新连接而不会发生前后两次连接数据错乱的情况。
TCP 与 UDP 的区别
| 特性 | TCP(传输控制协议) | UDP(用户数据报协议) |
|---|---|---|
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠,保证数据顺序和完整性 | 不可靠,可能丢包、乱序 |
| 传输方式 | 字节流,面向流 | 数据报,面向报文 |
| 流量控制 | 有(滑动窗口、拥塞控制等) | 无 |
| 速度 | 较慢(因需保证可靠性) | 较快 |
| 适用场景 | 文件传输、网页、邮件等 | 视频、语音、DNS、广播等 |
| 首部开销 | 20字节(不含选项) | 8字节 |
| 是否有顺序保证 | 有 | 无 |
| 是否有重传机制 | 有 | 无 |
TCP拥塞控制
慢启动
设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个rtt,拥塞窗口大小+1),以此来避免拥塞。将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值1,然后重新进入慢启动过程。
快速重传
在遇到3次重复确认应答(高速重发控制)时,代表收到了3个报文段,但是这之前的1个段丢失了,便对它进行立即重传。然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3的大小。这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。
OSI参考模型
| OSI模型层级 | Linux TCP/IP模型 | 常用协议示例 | 典型网络设备/功能 |
|---|---|---|---|
| 7. 应用层 | 应用层 | HTTP, FTP, SSH, DNS, SMTP | 网页服务器、邮件服务器 |
| 6. 表示层 | TLS, SSL, JPEG, GIF | 加密/解密、编码/解码 | |
| 5. 会话层 | RPC, NetBIOS, SMB | 会话管理 | |
| 4. 传输层 | 传输层 | TCP, UDP | 路由器、交换机(L4功能) |
| 3. 网络层 | 网络层 | IP, ICMP, ARP, IGMP | 路由器 |
| 2. 数据链路层 | 链路层 | Ethernet, PPP, VLAN, MAC | 交换机、网卡 |
| 1. 物理层 | 物理层 | RJ45, 光纤, 电缆, 无线信号 | 集线器、网线、无线模块 |
TCP/IP数据链路层的交互
网络层等在数据链路层用MAC地址作为通信目标,数据包到达网络层等往数据链路层发送的时候,首先会去ARP缓存表去查找ip对应的MAC地址,如果查到了,就将此ip对应的MAC地址封装到链路层数据包的包头。如果缓存中没有找到,则会发起一个广播,who is ip xxx tell ip xxxx,所有收到广播的机器看到这个ip是不是自己的,如果是自己的,则以单播的形式将自己的mac地址回复给请求机器。
浏览器堆URL的解析
浏览器要将URL解析为IP地址,解析域名就要用到DNS协议,首先主机会查询DNS的缓存,如果没有就给本地DNS发送查询请求。DNS查询分为两种方式,一种是递归查询,一种是迭代查询。如果是迭代查询,本地的DNS服务器,向根域名服务器发送查询请求,根域名服务器告知该域名的一级域名服务器,然后本地服务器给该一级域名服务器发送查询请求,然后依次类推直到查询到该域名的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议。得到IP地址后,浏览器就要与服务器建立一个http连接。因此要用到http协议。http生成一个get请求报文,将该报文传给TCP层处理,所以还会用到TCP协议。如果采用https还会使用https协议先对http数据进行加密。TCP层如果有需要先将HTTP数据包分片,分片依据路径MTU和MSS。TCP的数据包然 后会发送给IP层,用到IP协议。IP层通过路由选路,一跳一跳发送到目的地址。当然在一个网段内的寻址是通过以太网协议实现(也可以是其他物理层协议,比如PPP, SLIP),以太网协议需要直到目的IP地址的物理地址,又需要ARP协议。
其中:
- DNS协议,http协议,https协议属于应用层
- TCP/UDP属于传输层
- 传输层的任务就是负责主机中两个进程之间的通信。因特网的传输层可使用两种不同协议:即面向连接的传输控制协议TCP,和无连接的用户数据报协议UDP。面向连接的服务能够提供可靠的交付,但无连接服务则不保证提供可靠的交付,它只是“尽最大努力交付”。这两种服务方式都很有用,备有其优缺点。在分组交换网内的各个交换结点机都没有传输层。
- IP协议,ARP协议属于网络层
- 网络层负责为分组交换网上的不同主机提供通信。在发送数据时,网络层将运输层产生的报文段或用户数据报封装成分组或包进行传送。在TCP/IP体系中,分组也叫作IP数据报,或简称为数据报。网络层的另一个任务就是要选择合适的路由,使源主机运输层所传下来的分组能够交付到目的主机。
- 数据链路层
- 当发送数据时,数据链路层的任务是将在网络层交下来的IP数据报组装成帧,在两个相邻结点间的链路上传送以帧为单位的数据。每一帧包括数据和必要的控制信息(如同步信息、地址信息、差错控制、以及流量控制信息等)。控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。控制信息还使接收端能够检测到所收到的帧中有无差错
- 物理层
- 物理层的任务就是透明地传送比特流。在物理层上所传数据的单位是比特。传递信息所利用的一些物理媒体,如双绞线、同轴电缆、光缆等,并不在物理层之内而是在物理层的下面。因此也有人把物理媒体当做第0层。
HTTP/IP
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件,图片文件,查询结果等)。
特点
- 简单快速
- 客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活
- HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
- 无连接
- 无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 无状态
- HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
- 支持B/S及C/S模式。
- 默认端口80
- 基于TCP协议
https的建立过程
http请求响应步骤
- 客户端连接到Web服务器
- 一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接
- 发送http请求
- 通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
- 服务器接收请求并返回http响应
- Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
- 释放tcp连接
- 若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求
- 解析http内容
- 客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
http & https
区别
- HTTP协议是以明文的方式在网络中传输数据,而HTTPS协议传输的数据则是经过TLS加密后的,HTTPS具有更高的安全性
- HTTPS在TCP三次握手阶段之后,还需要进行SSL 的handshake,协商加密使用的对称加密密钥
- HTTPS协议需要服务端申请证书,浏览器端安装对应的根证书
- HTTP协议端口是80,HTTPS协议端口是443
HTTPS优点:
- HTTPS传输数据过程中使用密钥进行加密,所以安全性更高
- HTTPS协议可以认证用户和服务器,确保数据发送到正确的用户和服务器
HTTPS缺点: - HTTPS握手阶段延时较高: 由于在进行HTTP会话之前还需要进行SSL握手,因此HTTPS协议握手阶段延时增加
- HTTPS部署成本高: 一方面HTTPS协议需要使用证书来验证自身的安全性,所以需要购买CA证书;另一方面由于采用HTTPS协议需要进行加解密的计算,占用CPU资源较多,需要的服务器配置或数目高
http返回码
HTTP协议的响应报文由状态行、响应头部和响应包体组成,其响应状态码总体描述如下:
- 1xx:指示信息–表示请求已接收,继续处理。
- 2xx:成功–表示请求已被成功接收、理解、接受。
- 3xx:重定向–要完成请求必须进行更进一步的操作。
- 4xx:客户端错误–请求有语法错误或请求无法实现。
- 5xx:服务器端错误–服务器未能实现合法的请求。
常见状态代码、状态描述的详细说明如下:
- 200 OK:客户端请求成功。
- 206 partial content服务器已经正确处理部分GET请求,实现断点续传或同时分片下载,该请求必须包含Range请求头来指示客户端期望得到的范围
- 300 multiple choices(可选重定向):被请求的资源有一系列可供选择的反馈信息,由浏览器/用户自行选择其中一个。
- 301 moved permanently(永久重定向):该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URI之一。
- 302 move temporarily(临时重定向):请求的资源现在临时从不同的URI中获得,
- 304:not modified :如果客户端发送一个待条件的GET请求并且该请求以经被允许, 而文档内容未被改变,则返回304,该响应不包含包体(即可直接使用缓存)。
- 403 Forbidden:服务器收到请求,但是拒绝提供服务。
- t Found:请求资源不存在,举个例子:输入了错误的URL。
http1.0 & http1.1
HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议.主要区别主要体现在:
- 缓存处理
- 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,IfUnmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
- 带宽优化及网络连接的使用
- HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
- 错误通知的管理
- 在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
- Host头处理
- 在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
- 长连接
- HTTP 1.1支持长连接(PersistentConnection)和请求的流水线 (Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keepalive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
SOCKET
服务端:socket-bind-listen-accept
客户端:socket-connect
基于TCP的SOCKET:
- 服务器端程序
(1)、创建一个socket,用函数socket()
(2)、绑定IP地址、端口等信息到socket上,用函数bind()
(3)、设置允许的最大连接数,用函数listen()
(4)、接收客户端上来的连接,用函数accept()
(5)、收发数据,用函数send()和recv(),或者read()和write()
(6)、关闭网络连接 - 客户端程序:
(1)、创建一个socket,用函数socket()
(2)、设置要连接的对方的IP地址和端口等属性
(3)、连接服务器,用函数connect()
(4)、收发数据,用函数send()和recv(),或read()和write()
(5)、关闭网络连接

基于UDP的socket
- 服务器端流程
(1)、建立套接字文件描述符,使用函数socket(),生成套接字文件描述符。
(2)、设置服务器地址和侦听端口,初始化要绑定的网络地址结构。
(3)、绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定。
(4)、接收客户端的数据,使用recvfrom()函数接收客户端的网络数据。
(5)、向客户端发送数据,使用sendto()函数向服务器主机发送数据。
(6)、关闭套接字,使用close()函数释放资源。UDP协议的客户端流程 - 客户端流程
(1)、建立套接字文件描述符,socket()。
(2)、设置服务器地址和端口,struct sockaddr。
(3)、向服务器发送数据,sendto()。
(4)、接收服务器的数据,recvfrom()。
(5)、关闭套接字,close()。

send函数将要发送的数据从用户空间拷贝到TCP关联的内核发送缓冲区
recv函数从TCP关联的内核接收缓冲区中取出数据到程序定义的缓冲区
accept函数从连接队列里边儿取出已经成完成三次握手的连接
socket函数返回一个用于网络通讯的文件描述符
Server/Client
URL
URL 统一资源定位符(Uniform Resource Locator),其实就是我们访问web页面时需要输入的网页地址”网址”
完整定义如下:
- 协议类型 : // 登录信息(认证) @ 服务器地址 : 端口号 / 带层次的文件路径 ? 查询字 符串 # 片段标识符
URI 统一资源标识符(Uniform Resource Identifier),就是某个网络协议方案表示的资源的定位标识符,比如:https://www.google.com/ 也同样可以说是,在https网络协议下的一个URI。
GET/POST
- get参数通过url传递,post放在request body中。
- get请求在url中传递的参数是有长度限制的,而post没有。
- get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
- get请求只能进行url编码,而post支持多种编码方式。
- get请求会浏览器主动cache,而post支持多种编码方式。
- get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。
- GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制, 导致他们在应用过程中体现出一些不同。
- GET产生一个TCP数据包;POST产生两个TCP数据包。

