UDP:(主要问TCP和UDP的区别)
使用UDP还是TCP看数据可不可以丢。
例如客户端–服务器
UDP 可以直接 多个客户端给服务器发送数据,且服务器可以收到,因为不需要建立连接。
并且,服务器关闭,不关闭客户端,再次打开服务器,客户端仍然可以将数据把给服务器。
客户端发给服务器 的数据,如果服务器收不完,会直接丢掉。(每个数据包都会独立发送,)只要告诉目的端口,给谁都能发数据。
(如果数据丢失,可靠性在应用层实现)
ser.c
include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
//inet
int main()
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1)
{
exit(1);
}
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));//因为有第四个元素,需要置0,所以所兴都置为0;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000); //
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");//字符串转为无符号整形
int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(res == -1)
{
printf("bind error\n");
exit(1);
}
while(1){
char buff[128] = {0};
int len = sizeof(caddr);
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
//无符号整形专成字符串 无符号整形转字符串(打印点分十进制)
printf("port: %d,ip: %s,buff:%s\n",ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr),buff);
sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
}
cli.c
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1)
{
exit(1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
while(1)
{
char buff[128] = {0};
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,128);
int len = sizeof(saddr);
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
printf("recv:%s\n",buff);
}
close(sockfd);
exit(0);
}
《云服务器》使用
滑动窗口:
《计算机网络》5.7.1
超时重传的时间选择
必须考虑传输效率(三种传输机制)【坐公交】
TCP通过Nagle算法如何控制传输《TCP-IP详解卷一:协议》19章
- TCP维持一个变量,达到最大报文段MSS,就发送(延迟高)
- 由发送方指明要求发送报文段(TCP支持的推送操作)
- 发送方的计时器时限到了,这时就把已经有的缓存数据装入报文段,发送出去。
糊涂窗口综合征 :接收方从接收缓冲区一次仅读一个数据(一次仅腾出一个空间),向发送方确认,将发送窗口设置为1,但是发送方由40个字节,那就只能一写,一读。造成延迟,网络效率低。
解决方案:等接收方读取数据,腾出足够空间(容纳最长的报文段,或有一半空间空闲)
设置一个计时器:主动询问接收缓存区是否已满。
TCP 拥塞控制
前提:网络能够承受现有的网络负荷(全局性过程)交通堵不堵,取决于所有人。
拥塞控制:就是防止过多的数据注入到网络,使得网络中的路由器或者链路不会过载
发送端用发送窗口(SWND)限制了能连续发送给接收端的报文段数量
SWND 太小:网络延迟
SWND太大:网络拥塞。(连续发送的报文段太多)
接收端通过通知窗口(RWND)来控制发送窗口的(SWND)
SWND = min(拥塞窗口(CWND)和接收窗口(RWND)
- 慢启动和拥塞避免
慢启动:TCP模块刚启动发送数据的时候,并不知道网络的情况,因此以一种试探的方式,平滑的增加(指数增大) CWND的值。
(慢启动并不慢,如果不加以控制,就会造成网络拥塞)因此,设置慢启动门限,当拥塞窗口(CWND)达到这个值,就会进入拥塞避免状态。
拥塞避免:拥塞避免算法CWND以线性 (加法)增发,扩展变慢
如下图:
1.处理第一种拥塞,或者2发生在TCP重传定时器溢出的后面,也会处理2。
2.如果发生的是传送超时,那么会重传报文段,并且重传的方式会进行调整。最终拥塞控制进入慢启动阶段。
- 如何判断拥塞?
- 传送超时,TCP重传定时器溢出。
- 接收到重复的确认报文段。
- 快速重传和快速恢复
超时重传发生在超时之后
快速重传发生在超时之前。
超时重传:如果发送端连续收到三个重复确认报文段,便会执行重传。
快速恢复:当拥塞时,CWND发送减少为一半,如果仍然拥塞,减少为1半 的一半。(就不会进入慢启动阶段)
如下图:
(快速重传和快速恢复完成后将进入拥塞避免状态)
处理第2种情况。
例如 TCP报文段丢失,或者接收端收到乱序的TCP报文段并重排。
拥塞控制算法:判断当收到TCP的确认报文段,网络是否真的拥塞。
或者TCP报文段是否真的丢失?
如果发送端连续收到三个重复确认报文段,则认为网络拥塞。立即启动快速重传和快速恢复,完成之后将进入拥塞避免状态。