Posix API与网络协议栈


posix API

tcp网络编程主要学习的几个点,网络的api

在这里插入图片描述

socket

意思是插座,两部分组成,fd(文件描述符),tcb(tcp control block)tcp控制块,是协议栈里边的
任何文件的文件描述符fd,是从3开始的,因为0,1,2是系统的标准输入输出报错,比3小的已经被系统占有了
在这里插入图片描述

bind;

五元组(remoteip, remoteport, localip, localport, proto),最后一个参数是协议类型,bind绑定时,用来填充本机的ip与端口
socket与bind在tcp这段是做准备的,属于本地的操作与外界没有关系

TCP三次握手过程

客户端 服务端
在这里插入图片描述
这个问题,为啥会是三次,就是为了确保双向通信
握手的过程中,服务端这边是被动的,第一次握手,服务端接收到一个包,从整个数据包里边解析出一个五元组,从而构建出一个节点叫tcb,这个时候会把它加入到一个队列里边,叫半连接队列,也叫syn队列
第三次握手,服务端收到的数据,先查找半连接队列,如何去查找呢,通过五元组查找
半连接与全连接建立的前提是,先进入listen的状态,半连接队列里边所有tcb的状态是SYN RCVD的状态
全连接队列的时候,连接已经建立完了,然后调用accept生成clientfd
listen(fd,backlog);backlog指的是没有分配clientfd的tcb的总数,也就是半连接与全连接队列的长度之和,还有一种理解,全连接队列有多长,backlog就有多长。
服务器的端口有65535,如何做到百万级别的连接的呢
端口复用,fd—>tcb,通过五元组区分,五元组决定一个tcb,一个连接一个tcb。

数据发送

send与recv
send把应用空间的数据拷贝到协议栈里边去,拷贝到sendbuff里边去,然后协议栈加上tcp的头,以及各种协议的头,然后发送出去
recv,将接收的数据从内核协议栈的recvbuff,发送给应用层app
recvbuf在接收数据的时候,发送数据,有个push的标志位,置为1会通知对方来读
关于send发送的数据,要考虑粘包与分包的问题
有两种方式,在协议头加上这个包有多长,以及在包之间发分隔符,这两个方法能成功,有一个条件就是包是顺序的
在这里插入图片描述
那么tcp如何保证顺序的,顺序就是先发先到
有一个概念叫延迟ack,数据包是确定的,我们发10个包,第一个发过来,每隔发一个包,启动一个延时定时器,比如200ms,200ms之内发送完后,发一个包重置定时器。
如果200ms到了还没发出去,产生超时,对方没收到怎么回ack,就回4,意思就是在4以前,不包含4,以前的1,2,3都收到了,4进行重发
这个延迟ack的方式是在什么地方呢,在tcp的协议栈中做的
在这里插入图片描述

connect

我们再来说说,connect的函数,到底要不要等呢,是要等三次握手完成之后呢,还是说不要等,它等不等取决于刚开始创建的socket,有没有设置为阻塞的。socket创建的时候,就已经把fd与tcb就已经创建好了
在这里插入图片描述
fcntl();做了什么呢,跟协议栈没半毛钱关系,只跟fd有关系,设置fd的属性比如阻塞与非阻塞,是文件系统这一层。

udp

tcp都做的这么好了,为啥还要udp呢
tcp在弱网的环境下,大量的数据传输,是不合适的,因为丢包的时候,也会有大量的包进行重传。也无法保证实时性
udp的实用场景,比如说游戏,还有迅雷,百度网盘的下载速度限制

断开连接的过程

应用层这边只有一个函数close();
调用close这个函数的时候,会给内核协议栈发一个fin位,使得fin位置1,然后把fin包发输出去,然后接收方也会让recv函数返回0,然后准备一个ack的包发回去
接收方也调用close函数,跟发送方一样,发一个fin包,最后接收到发送方的ack,最后老死不相往来,双方都进入time_wait,tcb被回收。

发送方 接收方
在这里插入图片描述那么有没有那种情况呢,两边同时调用close,都发送了fin出去,这样就进入了一个closing状态,这种有,但是情况比较少。如果这样出现大量的time_wait,设置重用,设置reused,下一次再一次建立连接的时候,这个tcb还会拿出来使用。time_wait出现的原因是避免ack传输的丢失,双方会陷入一个死锁的状态,time_wait的时间是120s
在这里插入图片描述

进入fin_wait1后就会进入fin_wait2状态,接收方那边的内核也会进入close_wait状态
如果服务器出现了大量的close_wait状态,也就是接收方没有调用close,也可能使用业务逻辑问题,在代码中也就是recv=0的返回到close的过程太远,解决办法有,要么先调用close,要么就把期间业务抛到一个消息队列里边,让线程池去处理。
在这里插入图片描述
还有一个问题就是,比如在http的请求中,请求一个第三方的业务,这里出现了一个现象,出现了一个fin_wait2,并且一直卡在这里,怎么办呢
通过何种方法去脱离fin_wait2的状态
只有再等两分钟,服务器那边没有响应的时候,fin_wait2这一段会终止掉
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内容简介回到顶部↑ 本书是专为在UNIX平台下用C语言编制程序的人写的。是以POSIX为标准,主要以C语言为基础,详细介绍了UNIX平台下编写各种应用程序的范例和方法。全书分四个部分,共十五章。本书范例丰富,且具有代表性,如Socket编程、客户/服务端编程、多线程开发、CGI编程、X Windows下的Motif编程等。读者直接或只需稍作修改就可以将它们应用到自己的应用程序开发中。这些范例的源代码可以从配套光盘的电子书中直接拷贝使用。 目录回到顶部↑ 第一部分 基本的系统调用 第1章 文件子系统 1.1 文件子系统的基本概念 1.2 基本的文件输入和输出 1.3 高级的文件操作 第2章 终端操作 2.1 终端的基本概念 2.2 终端输入和输出 2.3 ioctl系统调用 第3章 进程及进程间通信 3.1 进程的基本概念 3.2 进程的一般操作 3.3 进程的特殊操作 3.4 进程间使用管道通信 第4章 信号 4.1 信号的基本概念 4.2 信号机制 4.3 有关信号的系统调用 第5章 部分其他调用 5.1 系统调用 .5.2 相关函数 第二部分 网络编程 第6章 Socket编程基础 6.1 TCP/IP基础知识 6.2 Socket一般描述 6.3 Socket中的主要调用 6.4 Socket的原始方式 第7章 客户/服务器编程 7.1 客户端程序设计 7.2 服务器端程序设计 7.3 服务端程序结构 7.4 多协议(TCP、UDP)服务端 7.5 客户端的并发程序设计 7.6 使用telnet协议的客户端例子 第8章 线程 8.1 有关线程的基本概念 8.2 线程的创建和终止 8.3 线程控制调用 8.4 线程之间的互斥 8.5 线程之间的同步 8.6 线程特定数据区的函数调用 8.7 一个使用线程的客户端并发的例子 8.8 有关线程的函数列表 第9章 CGl编程 9.1 CGI程序的基本概念 9.2 CGI基本编程 9.3 使用脚本语言编写CGl 9.4 Perl语言简介 9.5 一个简单的CGI例子 第三部分 X Window应用程序开发 第10章 X Window和Motif基础 10.1 简介 10.2 XWindow基本概念 10.3 启动Motif窗口管理器 10.4 设置Motif特性 10.5 Widget 第11章 Motif编程 11.1 基本编程概念 11.2 Widget资源 11.3 Motif编程基础 11.4 程序框架 11.5 "HelloWorld!"示例 11.6 管理器 11.7 按钮 11.8 X事件 11.9 其他Widget简介 11.10 菜单 11.11 对话框 第12章 Widget与X事件汇总 12.1 Widget 12.2 X事件 第四部分 常用的编程工具 第13章 编译器及调试工具 13.1 编译器用法入门 13.2 调试器使用入门 13.3 关于库的简介 第14章 Make工具及makefile规则 14.1 概述 14.2 make和makefile的关系 14.3 makefile规则 14.4 伪指令 14.5 make命令行参数 第15章 版本控制 15.1 版本控制概念 15.2 源代码控制系统SCCS 15.3 RCS使用方法 15.4 并发版本控制CVS

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值