TCP延申

粘包问题

粘包问题中的”包“,指的是应用层的数据包
TCP是基于字节流的,只维护发送出去多少,确认了多少,并不会维护消息和消息的边界,这就导致了粘包问题,他在应用层取数据的时候,不知道从哪里到哪里是一个完整的应用层数据包,面向字节流读文件都会有这种问题

在这里插入图片描述
数据就变得混乱了

怎么解决呢?

由于找不到应用层的数据始末,所以去TCP 上面做功夫肯定是不行的,所以解决这个问题就是要在应用层协议中加上包和包之间边界,比如在应用层数据报的结尾加上一个**;**这样在读取的时候,就能区分出一个完整的应用层数据报了,

在这里插入图片描述

在这里插入图片描述

读取http请求的

char buff[1024];
while(true)
{
	getline(sock,buffer);//按行读
	if(buff=="\n")
	{
	break;//报头读完了
	}
}
//在包头里面找到content-length=80
recv(sck,buffer,80)
  1. 定长发送,缓冲区大小都是1024
  2. 特殊字符,遇到这个字符就分离
  3. 自描述,自己进行定制协议

TCP 异常处理

TCP协议传输时会出现以下几种情况
连接崩溃的情况

  • 机器关机/重启:会释放文件描述符,发送FIN,和正常关闭一样,和进程终止是一样的
  • 进程终止:和机器重启一样,底层会自动4次挥手,文件描述符自动关

在进程毫无准备的情况下,突然结束进程,
我们知道TCP 连接是通过socket进行的,socket本质就是打开了一个文件,文件就存在于PCB的文件描述符表之中,每次打开一个socket文件都会在文件描述符表添加一项,删除会减少的一项
当强制结束进程时,PCB没了,里面的文件描述符表也没了,就相当于自动关闭了,也依然会执行四次挥手的过程

  • 网线断开/机器断电:断电时没有时间给操作系统去反应,来不及四次挥手,如果客户端断电,客户端不会给服务器发送任何数据,服务器会尝试重新连接,重连一定次数的话,就会放弃连接,接收端的连接还在,当接收端对我进行写入,会收到一个reset然后TCP 内不设置一个保活定时器(比较鸡肋),询问对方是否还在,不在就释放连接

    但是最好不要把保活定时器作为一个应用层的工具,因为不同的应用层对于连接是否需要关闭是不一样的,比如QQ,在断线之后,也会定期尝试重新连接

用UDP实现可靠传输

  • 引入序列号:保证数据的顺序型
  • 引入确认应答机制:对端收到的数据都要进行应答
  • 超时重传:数据隔一段时间没收到进行重新传
  • 校验和:使用校验和,避免发送错误
  • 流量控制:对发送的数据进行管理

TCP 太重了,udp比较轻量化

TCP相关实验

理解Listen的第二个参数

listen第二个参数+1=在TCP层建立正常连接的个数,不是只能在服务器段维护几个连接

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "port" << endl;
        exit(1);
    }
    uint16_t port = atoi(argv[1]);
    int sockfd = Sock::Socket();
    Sock::Setoptsocket(sockfd);
    Sock::Bind(sockfd, port);
    Sock::Listen(sockfd);
    while (1)
    {
	//这里我们没有调用accept
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述
Linux内核协议栈为一个TCP连接管理使用两个队列

  1. 半连接队列(用来保存处于SYN_RECV和SYN_SEND状态的请求),握手之中
  2. 全连接队列(acceptd队列)(用来保存处于established状态,但是应用层没有调用accept取走的请求,暂时没有被读取),握手成功

全连接队列长度会受listen第二个参数影响(n+1):长度至少为1

为什么要维护队列(全链接)?为什么这个队列不能过长?为什么这个队列不能没有?

在这里插入图片描述

  1. 上层的服务太忙了, 服务打满了,来不及去接收新的服务,只能让它在队列里面(避免内部资源没有被充分利用)
  2. 当内部满的时候,一旦有人退出,就可以立马把队列里面的取走,保证内部资源被100%利用
  3. 如果把队列弄太长了,维护队列也是有成本的,成本太高了,长时间链接没有反应,客户就会把服务关掉,把省出来的,让服务去使用,让服务以较高的效率提供服务
  4. listen就相等于在门口叫号的
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevin~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值