TCP/UDP协议详解
TCP协议详解
TCP连接是全双工的,即双方的数据读写可以通过一个连接执行。
TCP协议的连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服务。
而无连接的UDP协议适合于广播和多播。
TCP和UDP的区别:
TCP为应用层提供可靠的、面向连接的、基于流的服务
(1)①TCP采用发送应答机制,发送端发送的每个TCP报文段都必须得到接收方的应答,才认为这个TCP报文段传输成功。
②TCP协议采用超时重传机制,发送端发出一个TCP报文段,如果在规定时间内未收到应答,它将重发该报文段。
③TCP协议对接收到的TCP报文重排,整理再交付给应用层,所以TCP是可靠的。
(2)使用TCP 协议通信的双方,必须先建立TCP连接,并且在内核中为该连接维持一些必要的数据结构(状态、读写缓冲区、定时器等)。当通信结束时,通信双方必须要断开TCP连接,以释放内核维护的数据。所以TCP是面向连接的。
(3)基于流的数据没有长度限制,它源源不断的从通信的一端流入另一端。
当发送端应用程序执行多次写操作的时候,TCP模块先把这些数据放入到TCP发送缓冲区中,当TCP模块真正开始发送数据的时候,发送缓冲区中的数据可能被封装成一个或多个TCP报文段发送。所以TCP报文段的个数与应用程序执行的写操作次数之间没有关系。
当接收端收到一个或多个TCP报文段后,TCP模块将它们携带的应用程序数据按照TCP报文段的序号依次放入到TCP接收缓冲区中,并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收端缓冲区中的数据读出,也可以分多次读取,这取决于用户指定的应用程序读取缓冲区的大小。所以应用程序的读操作次数和TCP模块接收到的TCP报文段个数没有关系。
综上,写操作的次数和读操作的次数无关。这就是基于流的服务。
TCP可以修改的参数:
1.可以修改内核变量来启用或者关闭窗口扩大因子选项
2.可以修改内核变量来启用或者关闭选择性确认选项,SACK
3.可以修改内核变量来启用或者关闭时间戳
32位序号:Seq号,表示从TCP发送端向TCP接收端发送的数据字节流,它表示在这个报文段中的第一个字节。在主机A发给主机B的第一个报文段中,序号被初始化为某个随机值。
该主机要发送数据的第一个字节序号为这个ISN+1.
Seq是数据包本身的***,是为了连接以后传送数据用的,
Ack是对收到的数据包的确认,是等待接收的数据的***
32位确认号:Ack号,用作对另一方发送来的TCP报文段的响应,其值是收到的TCP报文段的序号值+1,即 确认方Ack = 发起方Seq + 1.
【只有ACK标志值为1 时,确认序号字段才生效】
4位头部长度:标识该头部有多少个4字节。4位最大表示15,所以头部最长为60字节。【这一点和IP头部相同】
6位标志:
URG:紧急指针
ACK:确认报文段
PSH:提示接收端应用程序应该立即从TCP接收缓冲区中读取数据,为接收后续数据腾出空间
RST:复位报文段
SYN:同步报文段
FIN:结束报文段
16位窗口大小:是TCP流量控制的一个手段,它告诉对方本端的TCP接收缓冲区还能容纳多少数据,这样对方就可以控制发送数据的速度。窗口大小是字节数,16位窗口大小说明窗口大小最大为6655字节。
16位校验和:检验TCP报文段在传输过程中是否损坏,这是TCP传输的一个重要保障。检验TCP首部和TCP数据。一定是发送端计算和存储,接收端进行验证。
16紧急指针:发送端向接收端发送紧急数据的方法
TCP编程流程:
服务器:socket、bind、listen、accept、recv、send、close
客户端:socket、connect、recv、send、close
int socket(int domain,int type,int protocol);
成功返回文件描述符,失败返回-1
int bnid(itn sockfd,struct sockaddr* myaddr,socklen_t addrlen);
成功返回0,失败返回-1
int listen(int sockfd,int backlog);
成功返回0,失败返回-1
backlog是内核监听队列的最大长度,典型值是5,表示可以监听6个队列
/*
backlog使用两个队列实现,一个是SYN队列,一个是accept队列,三次握手中,服务器监听到有连接请求时,将处于SYN_RECV状态的连接放入SYN队列中,当服务器端连接的状态改变为ESTABLISH时,将SYN队列中的连接放入accept队列。所以,accept系统调用仅仅是从监听队列中取出连接。
*/
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
UDP协议详解
UDP为应用层提供不可靠、无连接和基于数据报的服务
(1)如果数据在传输途中丢失,或者目的端通过数据校验,发现数据错误而将其丢弃,UDP只是简单的通知应用程序发送失败。所以UDP不可靠。它需要上层协议来处理数据确认和超时重传。
(2)通信双方不保持一个长久的联系,因此应用程序每次发送数据都需要明确指定接收端地址(IP地址等信息)
(3)发送端应用程序每执行一次写操作,UDP模块就将其封装成一个UDP数据报并发送它,同时接收端必须及时读取这个UDP数据报,否则就会丢包(发生在较慢的服务器上),并且,如果用户没有指定足够的应用程序缓冲区来读取UDP数据,UDP数据将被截断。
UDP编程流程:
服务器:socket、bind()、recvfrom、sendto、close
客户端:socket、sendto()、recvfrom()、close
ssize_t recvfrom(int sockfd,void*buff,size_t len,int flags,struct sockaddr* from,size_t *addrlen);
前3个参数和recv一样,flag是可选项参数,没有就填0,第5个参数是发送端sockaddr结构体变量的地址,第6个参数是from结构体的长度的变量地址
成功返回接收数据的长度,失败返回-1
ssize_t sendto(int sock,void* buff,size_t len,int flag,struct sockaddr* to,size_t *addrlen)
最后一个参数只是长度,不是长度变量的地址
我们为什么不直接使用IP协议而要额外增加一个UDP协议呢?
因为在IP协议中并没有端口的概念,IP协议是一个IP地址到另一个IP地址的传输,是一个主机到另一个主机的对话。但是每台计算机需要多个通信的通道,所以就需要端口。
有了TCP为什么还要UDP?
我们如果只使用TCP、IP通信的话,每次都需要建立连接,会造成很大的网络负担,因此就需要一个不建立连接的协议,因此UDP就产生了。
TCP和UDP的使用场景?
(1)对网络通信质量有要求的时候,数据 要准确无误的传递给对方时,这往往是在一些要求可靠的应用上,比如HTTP,HTTPS,FTP等。
(2)要求网络通信速度尽可能的快,可以使用UDP。