《UNP》的零碎知识点总结

。套接字工作在应用层和传输层之间,套接字之上为用户进程,套接字之下4层是构成操作系统内核的一部分,上三层大部分关注网络应用的细节,下四层大部分关注通信细节

用于发现网络细节的两个基本命令,netstat和ipconfig

分组过滤器:用来截获和过滤一个被置为混杂模式的网络接口的分组

应用进程往一个UDP套接字写入一个消息,该消息随后被封装成一个UDP数据报,进而又被封装成一个IP数据报,然后发送到目的地,UDP不保证数据报可达,也不保证其按序到达,也不保证只到达一次,每个UDP数据报都有一个长度字段,所以说UDP是有消息边界的,同时UDP是无连接的,它体现在一个UDP服务器可以用同一个套接字从若干不同的客户接收数据报,而一个客户端也可以通过一个UDP套接字向多个服务器发送数据报

TCP是有连接的,两端传输数据必须是先建立连接,传输完成后需要断开连接,TCP还含有用于估算往返时间RTT的算法,以便作为设置超时重传的参考,TCP提供了序列号来保证数据的有序,以及判定是否重复和缺失,此外TCP还提供流量控制,TCP连接还是一个全双工的连接

SCTP是面向消息的,它也是有连接的,但它使用了“关联”来取代“连接”,是因为SCTP支持多宿而涉及不止两个地址。SCTP在连接的多个端点上提供多个流,每个流相互独立的完成可靠传输。比如一个端点可能含有多个冗余的网络连接,如果它的某个网络发生故障,则可以切换到已关联的端点的另一个地址。

三次握手:客户端通过调用connect发送一个SYN分节,告知服务器将要发送的数据报的初始序列(此时客户端处于SYN_SENT态),该分节通常不携带数据,只包含IP首部和TCP首部,然后阻塞等待服务器的确认(这一步称为主动打开),服务器阻塞在accept等待一个主动连接的到来(处于LISTEN态),然后回送一个ACK(ACK为确认号,是客户端初始序列号+1,因为一个SYN和一个FIN都只占一个序列号空间),同时发送自己的SYN(被动打开)(处于SYN_RCVD态),客户端收到ACK从connect返回(处于ESTABLISHED态),并回复服务器的ACK,服务器收到ACK后从accept返回,至此连接建立(处于ESTABLISHED态) 图2-5

四次挥手:客户端close发起主动关闭,发送一个FIN(处于FIN_WAIT_1态),服务器端回复ACK(处于CLOSE_WAIT态),客户端接收ACK(处于FIN_WAIT_2态),四次挥手的而不是三次的原因就是存在一种叫做半关闭的状态,一段时间后,服务器端发送FIN(处于LAST_ACK态),客户端接收并回复ACK(TIME_WAIT),2MSL后挥手完成(处于CLOSED态) 图2-5, 其中2MSL的含义是最长分节周期的两倍,如果没有这个状态,客户端发送最终的ACK后不维护状态信息,假设ACK丢失,服务器端未收到ACK,超时重传FIN,客户端将会响应一个RST,服务器会将这个解释为错误分节。还有一个理由是,2MSL保证了成功建立一个TCP连接时,相同两端点之间之前可能建立过连接,它们端老分组已经在网络上消逝了

一个UNIX进程无论自愿还是非自愿地终止时,所有打开的描述符都将会被关闭,这也会促使一个FIN的发送

SCTP是四次握手(初始化消息INIT和其ACK,以及客户端对服务器状态cookie端回射及确认)和三次挥手(不存在半关闭状态)

服务器选择接口时可以指定一个接口或者任意接口,但不能指定一个包含多个地址端清单

IPv4数据报端最大大小是65535(2^32),包括IPv4首部
以太网端MTU(最大传输单元)是1500,两主机之间最小的MTU称为路径MTU,因特网中录有选择往往是不对称端,所以来回路径MTU通常不相同
当一个IP数据报从某个接口(主机或路由器(ipv6路由器不执行分片))发送出去时,如果它端大小超过了响应的链路(接下来要传输的线路)的MTU,则将会执行分片,如果ipv4设置不分片位(DF,IPv6默认设置),超过链路MTU时,则会返回出错消息

TCP发送数据:每一个套接字有一个发送缓冲区,当调用一个write时,如果应用程序端缓冲区的空闲大小大于套接字发送缓冲区,则write会被阻塞,write端成功返回只代表应用缓冲区的数据都已经进入了发送缓冲区,并不能代表都已经到达目的地。TCP会为发送的数据留一个副本在发送缓冲区,直到ACK到达,数据才会被丢弃

UDP发送数据:UDP套接字端发送缓冲区并不是一个真实存在的,因为发送端并不需要保留副本,因为它是不可靠的,他的作用只是为了限制写到该套接字的UDP数据报的大小上限

小端法:高地址存高字节,低地址存低字节
大端法:高地址存低字节,低地址存高字节

如果指定端口号为0,那么内核就在bind的时候选择一个临时端口。然而如果指定IP地址为通配符,那么内核将等到套接字已连接或已在套接字上发出数据报的时候才选择一个本地IP地址。如果使用的是临时端口,要获取端口号必须调用getsockname来返回协议地址,因为第二个参数是const

TCP服务器内部维护着两个队列,一个已完成连接队列,里面的元素处于三次握手完成,马上从accept返回(ESTABLISHED),一个未完成连接队列,处于收到了客户端的SYN,但三次握手还没完成(SYN_RCVD),如果两个队列是满的,服务器就会忽略后面到来的SYN请求,直到队列有空闲

存放在硬盘上的可执行程序文件能够被执行的唯一方法是调用6个exec函数中的某一个

accept可以返回一个已连接套接字的描述符以及客户端的地址信息,我们可以fork一个子进程来处理这个连接,但是有一种情况就是如果我们使用inet超级服务器,那么操作就变成了fork一个子进程后由子进程启动响应的服务器程序来为客户端服务,问题就出现了,子进程调用exec启动程序后,子进程的内存映像被替换成了新的服务器的程序文件,所以之前返回的客户端地址信息也就不见了,此时我们就只能通过只能通过使用getpeername获取客户端的IP地址和端口号,但是套接字虽然对子进程开放,但是新程序启动后我们并不知道描述符的值是多少,有两种方法可以获取,1.将值作为参数传进新程序,2.这个是一个巧妙的方法,也是inet超级服务器所用的方法,将描述符0,1,2置为连接描述符

信号有时也称为 软中断 ,有一个进程产生发送给另一进程(或自身),或是由内核发送给某个进程
硬中断 是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)

一旦进程安装了信号处理函数,它便会一直安装着直到进程结束。在一个信号处理函数运行期间,正被递交的信号会阻塞.一个信号产生了多次但在该信号解阻塞后只会被执行一次,因为信号默认是不排队的。可以利用sigprocmask函数,选择性的阻塞或解阻塞一组信号,如果在某一段临界区代码(每个进程中访问临界资源(临界资源是一次仅允许一个进程使用的共享资源)的那段程序)执行期间,我们可以使用该函数防止捕获某些信号以保护这段代码

当阻塞域某个慢启动调用的一个进程捕获某个信号且相应信号处理函数返回时,该系统可能会返回一个EINTR错误

如果一个父进程同时fork两多个子进程,并希望在后面循环调用wait等待子结束,但这样很有可能会产生僵死进程,因为信号是不排队的,当我们处理第一个子进程结束传来的SIGCHLD信号时,可能其他的子进程也会传来这个信号,但只会阻塞一个该信号,于是便会产生僵死进程,此时正确的处理方法是使用waitpid,它可以指定它可以指定WNOHANG选项,高值waitpid在还有尚未终止的子进程时不要阻塞

IO模型:
阻塞式IO
非阻塞式IO:基本思路是轮询的查询一个描述符是否准备好
IO复用:select,poll,epoll
信号驱动式IO模型:基本思路是调用sigaction(系统调用)注册一个信号处理函数,sigaction立即返回,当有描述符被激活时,内核为进程产生一个SIGIO信号,告知描述符可用(有数据报到达已准备好处理)
异步IO模型:告知内核启动一个IO操作(与信号驱动式IO的区别是,信号驱动IO由内核告知何时可以启动一个IO,异步IO由内核告知IO操作何时完成)

当读取文件中的数据发送到网络中时,有一个问题,当我们读到文件尾时,不应该立即返回,因为我们发送数据是批量处理的,所以此时网络中可能还存在发送到对端的请求或数据报或者对端发来的应答或ack,所以此时就应该用shutdown变为所谓的半关闭状态,告知对端,我已经发送完成

pselect相比于select的区别:
1.使用了timespec结构,使我们控制的时间精度更高(纳秒,原结构为微秒)
2.增加第6个参数sigmask,pselect可使用一可选择的信号屏蔽字,如果sigmask为空,则与select相同,若不为空,则在调用时会以原子方式安装该信号屏蔽字,返回时回复以前的信号屏蔽字。

获取和设置影响套接字选项的方法:
getsockopt和setsockopt
fcntl函数(设为阻塞或非阻塞IO)
ioctl函数

一般来说,大部分TCP服务器是并发的,UDP服务器是迭代的

事实上,每个UDP套接字都有一个接收缓冲区,到达该套接字的每个数据报都进入则个套接字接收缓冲区,当进程调用recvfrom时,缓冲区中的下一个数据报以FIFO顺序返回结果

给UDP套接字加一个超时重传并不能保证它的可靠,因为我们并不能判断到底是数据报没有到达服务器还是服务器的应答没有到达客户端

ICMP异步错误:UDP输出操作的成功返回仅仅表示在接口输出队列中具有存放所形成的IP数据报的空间。但ICMP错误将会在后来才返回(所以是异步的),且并不返回给进程,只有UDP套接字建立连接后,这些错误才会返回给进程,错误消息包含引发错误的数据报的IP首部和UDP首部

客户端的临时端口是在第一次调用sendto时一次性选定的,不能改变,但是IP地址可以随意变动

UDP的connect函数没有三路握手过程,内核只检查是否存在立即可知的错误(例如目的地不可达),记录对端端口号和IP地址,然后立即返回,对于以连接的UDP套接字有三个变化:
1.在也不能给输出操作指定IP地址和端口号(sendto变为write或send)
2.不用使用recvfrom获取数据报发送者,改用read,recv,recvmsg
3.异步错误会返回给调用进程

对于多个发送给同一个对端的数据报而言,显示连接套接字效率更高,默认情况下:
1.连接套接字
2.发送数据报1
3.断开套接字
4.连接套接字
5.发送数据报2
6.断开套接字
。。。。。。。
连接的情况下:
1.连接套接字
2.发送数据报1
3.发送数据报2
。。。。。。。
n:断开套接字

DNS:主机名字和IP地址之间的映射
DNS中的资源记录:
A:把主机名映射成IPv4地址
AAAA:把主机名映射成IPv6地址
PTR:把IP地址映射为主机名
MX:把一个主机指定作为给定主机的邮件交换器
CNAME:为常见的服务指派CNAME记录

应用程序调用解析器函数使用解析器代码,解析器代码读取配置文件,查询到本地名字服务器的地址,使用UDP向本地名字服务器发出查询,如果本地名字服务器不知道答案,则会使用UDP在整个因特网上查询其他名字服务器,如果答案太长,超出了UDP的承载能力,则会本地名字服务器和解析器会自动切换为TCP

DNS的替代方法:静态主机文件, 网络信息系统(NIS), 轻权目录访问协议(LDAP)

双栈主机其上的IPv6服务器既能处理IPv4客户也能处理IPv6客户, 这是通过使用IPv4映射的IPv6地址实现的,服务器端的数据链路层通过查看以太网类型字段把每个帧传递给相应的IP模块,如果是IPv4,则把该数据报IPv4首部中的源IPv4地址转换成一个等价的IPv4映射的IPv6地址,一般来说IPv6地址无法标示成一个IPv4地址,所以本条内容前面说的是IPv6服务器

如果双栈主机上的IPv6客户连接一个IPv4服务器,那么返回调用解析器函数返回给客户的是IPv4服务器的IPv6映射,客户发送IPv6数据报,内核检测到这个映射后改为发送一个IPv4数据报

守护进程的启动方法:
1.系统启动阶段由系统初始化脚本启动
2.许多网络服务器(守护进程)由inet超级服务器启动
3.cron守护进程按照规定定期执行一些程序(守护进程)
4.at命令用于指定将来某个时刻的程序执行(实际上当这些时刻到来时,也是由cron守护进程来启动它们)
5.从用户终端或在前台或在后台启动,但这样的守护进程必须亲自脱离域与控制终端的关联(守护进程的基本规则),从而避免与作业控制,终端会话管理,终端产生信号等发生任何不期望的交互,也可以避免在后台运行的守护进程非预期的输出到终端

因为守护进程没有终端,所以不能像普通进程一样发送信息到终端,所以此时syslog函数就是输出守护进程消息的标准方法,

daemon_init函数将普通进程变为守护进程,实现方法是:
1.fork一个子进程,并关闭父进程,确保了该进程不是一个进程组的首进程
2.创建一个新会话,确保没有控制终端
3.再fork子进程关闭当前该子进程的父进程,保证了不是会话首进程
到此,一个守护进程的所有要求就都满足了

inet超级服务器的工作流程 图13-7

inet超级服务器创建的子进程服务器必须接管连接套接字直到自己终止,意味着,inet超级服务器应该关闭该连接套接字,防止inet超级服务器让select监听该连接套接字的可读性(因为已经交于子进程服务器了)

在涉及套接字的IO操作上设置超时的方法有3中:
1.alarm,缺点有很多,首先涉及信号但不是原子操作,其次信号处理在不同的实现上存在差异,而且还会干扰进程中现有的alarm
2.select阻塞等待IO,select自带时间限制
3.SO_RCVTIMEO和SO_SNDTIMEO选项,但并非所有实现都支持这两个套接字选项

辅助数据通过sendmsg和recvmsg这两个函数,使用msghdr结构中的msg_control和msg_controllen两个成员发送和接收,文件描述符只能使用UNIX域套接字传递的原因就是UNXI域套接字支持这两个函数,且文件描述符需要使用辅助数据承载

当使用标准函数库中的函数作用于套接字时应该注意以下几点
1.fdopen从一个描述符创建出一个标准IO流,fileno获取一个标准IO流对应的描述符(当想用select作用于一个标准IO流时使用,因为select只用于描述符)
2.便准IO流可以是全双工的(r+),在调用一个输出函数后,需要插入一个fflush,fseek,fsetpos或rewind调用才能能接着调用一个输入函数(冲洗缓冲区,因为此时标准IO库是完全缓冲),在调用一个输入函数后,也需要插入一个fseek,fsetpos或rewind调用才能能接着调用一个输出函数,除非遇到EOF
3.解决2问题最简单的方法是打开两个流

不同缓冲区在下列情况下才发生IO:
完全缓冲:缓冲区满(默认通常为8192字节)或显示调用fflush等能冲洗缓冲区的函数,或进程调用exit终止自身
行缓冲:遇到换行符或显示调用fflush等能冲洗缓冲区的函数,或进程调用exit终止自身
不缓冲:每次标准IO都发生IO

/dev/poll与poll和select的区别是,只要在循环等待前往/dev/poll轮询设备上写入一个所关心事件列表就可以不用在每次循环时都传递带查询描述符了,适用于重复轮询大量文件描述符的应用程序, 轮询的文件描述符相对稳定,意味着描述符不是不断关闭和重新打开, 与要轮询的文件描述符总数量相比,实际具有待处理的已轮询事件的文件描述符组很小

epoll(linux)想对kqueue(FreeBSD)的缺陷是:
1.它不能在单次系统调用中多次更新兴趣集。当你的兴趣集中有100个文件描述符需要更新状态时,你不得不调用100次epoll_ctl()函数
2.epoll是基于文件描述符工作,当你想对非文件类型提供支持时只能调用signalfd(),eventfd()和timerfd_create()等来将非文件类型转换成文件类型,但这很麻烦,kqueue是基于事件工作的,除了描述符以外,它还可以关心异步IO的通知,文件修改通知,进程调用exit或fork等进程状态的通知,信号处理

T/TCP事务目的TCP:简单来说就是将SYN,FIN,以及数据都捆绑在一起发送,适用于只是针对请求-应答而不需要相互之间传递多个数据报(数据极少保证可以和SYN,FIN加起来只有一个包也行)的服务

UNIX域协议并不是一个实际的协议簇,而是在单个主机上执行客户/服务器通信的一种方式
UNIX域套接字比在同一主机上运行两个TCP(UDP)套接字的优势有3点:
1.速度快出1倍
2.可以在同一主机的不同进程之间传递文件描述符
3.可以把客户的凭证(用户ID,组ID)提供给服务器,以提供额外的安全检查措施

UNIX域数据报协议域UDP不同之处在于由一个未绑定的UNIX域数据报套接字发送数据报不会隐式的给这个套接字捆绑一个路径名,因此必须显示的调用bind

两个进程件传递文件描述符的步骤:
1.创建一个字节流或数据报的UNIX域套接字
2.获取一个打开描述符
3.发送进程创建一个msghdr结构,其中含有待传递的描述符,描述符作为辅助成员发送,发送一个文件描述符会使计数器+1,即使在sendmsg后关闭该描述符,对于接收进程,它仍是打开状态
4.接收进程调用recvmsg在步骤1中的套接字上接收这个描述符

套接字操作默认是阻塞的
输入操作:read, readv, recv, recvfrom, recvmsg
输出操作:write, writev, send, sendto, sendmsg
接收外来连接:accept
发起外出连接:connect

路由套接字:路由表相关操作

UDP相比TCP的优势:
1.支持广播和多播
2.没有连接的建立和拆除

TCP最小事务处理时间:2 x RTT+SPT
UDP最小事务处理时间:RTT+SPT
图13-7

TCP相比UDP的优势:
1.正面确认,丢失分组重传,重复分组检测, 给被网络打乱次序的分组排序
2.窗口式流量控制
3.慢启动和拥塞避免

带外数据是指比普通数据优先级更高的数据(TCP没有真正意义上的带外数据,而是紧急模式)

客户服务器心搏函数原理就是周期性的使用紧急模式轮询对端,而不使用保护机制的原因是,时间太长(2小时),且其不是由每个套接字维护的,更改保活计时器参数将会影响所有套接字

sigsuspend函数先保存当前信号掩码,再把当前信号掩码设置为它的参数,然后等待捕获信号,信号到来执行信号处理函数,信号处理函数返回后将当前信号掩码设置为之前保存的值,然后返回

信号驱动IO的核心是把IO放在SIGIO信号的信号处理函数里面

线程也被称为轻权进程,同一进程中的所有线程共享大多数数据,但每个线程有各自的:线程ID, 寄存器集合,程序计数器和栈指针,栈, errno, 信号掩码,优先级

信号处理函数也被视为一种线程

线程特定数据的模型:图26-10

原始套接字拥有普通TCP或UDP套接字不具备的能力:
1.进程读写ICMPv4(ping程序),IGMPv6和ICMPv4等分组
2.进程可以读写内核不处理其协议字段的IPv4数据报(比如OSPF路由协议即不使用TCP,也不使用UDP,而是通过收发协议字段为89的IP数据报而直接使用IP,而直接读写这些IP数据报就要用到原始套接字)
3.有了原始套接字,进程可以自行构建IPv4首部

只有超级用户才能创建原始套接字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值