您好,欢迎访问三七文档
当前位置:首页 > 机械/制造/汽车 > 汽车理论 > 通信应用软件设计TP8
第7章揭密通信应用软件设计2目标了解socket底层数据结构掌握发送和接收缓冲以及TCP的关系了解TCP的性能了解TCP套接字的生存期了解多路复用的底层实现3概述如果不理解套接字的具体实现所关联的数据结构和底层协议的工作细节,就很难领会网络编程的一些精妙之处。本章描述了在创建和使用套接字时“底层”所发生的一些事情。本章的描述仅仅涵盖了一些普通的事件序列,而略去了许多细节。4与套接字关联的数据结构(1)5与套接字关联的数据结构(2)本地IP和端口远程IP和端口发送队列SendQ和接送队列RecvQ协议状态:对于TCP套接字,还包含与打开和关闭TCP握手相关的额外的协议状态信息,所有的套接字状态都开始于Closed状态。6netstat该命令可以获取底层数据结构的“快照”7TCP发送特点一般来讲,在TCP套接字上完成send()调用并不意味者实际地传输数据—而只是把它们复制到了本地缓冲区。在正常情况下,它将被立即传输,但是精确的传输时间由TCP(而不是应用程序)控制。由于TCP提供了可靠的字节流服务,通过TCP套接字发送的任何数据的副本都必须由TCP实现保存起来,直到其在连接的另一端被成功接收为止。字节流服务性质意味着在输入流中不必保留消息边界。8UDP发送特点对于数据报(UDP)套接字,不会为了重传而缓冲分组,在send()的调用返回时,就把数据提供给网络子系统以进行传输。如果网路子系统由于某种原因无法处理消息,将不会给出任何提示地丢弃分组。9缓冲和TCP(1)在使用TCP套接字时要记住的最重要的事情是:不能假设写到连接一端的数据大小与从连接另一端读取的数据大小之间存在任何一致性。考虑如下程序:10缓冲和TCP(2)SendQ:发送端底层发送队列RecvQ:接收端底层接收队列Delived:接收者已经从输入流中读取的字节11缓冲和TCP(3)12死锁风险(1)在设计应用程序时,必须小心地避免死锁,在这种状态中,对应的每一方都被阻塞,并等待另一方执行某种动作。一旦RecvQ满江阻止对端的SendQ发送。可能存在这样的情况:一方发送大量的数据导致对端的RecvQ满从而使本方SendQ发送阻塞,而对端也在大量的发送数据从而导致本方的RecvQ满从而阻塞对端的发送。13死锁风险(2)结论:要仔细设计协议,以避免在两个方向上同时大量发送数据。14关于性能SendQ和RecvQ缓冲区的大小会影响到通过TCP连接实现的吞吐量(throughput)。吞吐量是指从发送者发送可供接收程序使用的用户数据字节时所采用的速率。在没有网络流量或其他限制的情况下,更大的缓冲区一般能够实现更高的吞吐量。可以通过SO_RCVBUF和SO_SNDBUF套接字选项更改发送和接收缓冲区的大小。思考题:发送和接收缓冲区大小如何考虑?15TCP套接字的生存期在创建新的TCP套接字时,不能把它立即用于发送和接收数据。首先需要把它连接到远程端点。更详细地考虑底层结构如何实现连接状态,将有助于程序的可靠性。16连接假设客户的Internet地址为:A.B.C.D,服务器的地址为:W.X.Y.Z,服务器端口号为Q。当客户利用服务器的IP地址调用connect()时,底层实现将会创建一个套接字实例:它最初处于closed状态,如果客户没有利用bind()指定本地地址/端口,实现就会选择尚未被另一个TCP套接字使用的本地端口号(P)和本地IP地址。17客户端建立连接18服务器端的套接字设置19处理传入的连接请求20accept()调用21关闭TCP连接TCP有一个优雅的关闭(gracefulclose)机制,它允许应用程序在终止连接时不必担心可能仍在传输数据会丢失。应用程序通过调用close()或shutdown()来指示它在连接的套接字上完成了数据发送。此时,底层TCP首先将传输保留在SendQ中的数据,然后向另一端发送一条关闭TCP的握手消息,并等待对方的确认消息。22主动关闭TCP连接23在另一端关闭后执行关闭24解决关闭时数据丢失问题调用close会终止两个方向上的传输,并导致与套接字关联的文件描述符被取消分配。保留在RecvQ中任何未递送的数据都会被丢弃。最佳的解决方案是设计一种应用程序协议,使得无论哪一端首先执行关闭,仅当它接收到关于数据已接收的应用程序级的保证后,它才能这样做。25解多路复用揭密对于TCP和UDP来说,解多路复用可以归纳为以下几点:套接字结构中的本地端口号必须与传入中的分组中得目的端口号匹配在套接字结构中,任何包含通配符(*)的地址字段都被认为与分组中相应的IP字段的任何值相匹配如果多个套接字结构与传入的分组之间对于全部4个地址字段都匹配,那么使用最少通配符进行匹配的地址字段将获得该分组。26端口绑定当程序试图调用bind()以绑定到特定的本地端口时,将检查现有的套接字以确保没有其他套接字已经在使用那个本地套接字。当一个进程结束时,套接字的端口号还不能被重新利用,主要是底层套接字还处于Time-Wait状态。解决上述问题方法:方法一、等待底层结构离开Time-Wait状态方法二、在调用bind()之前设置SO_REUSEADDR套接字选项。27利用多个匹配的套接字进行解多路复用
本文标题:通信应用软件设计TP8
链接地址:https://www.777doc.com/doc-3156607 .html