当前位置: 首页 > news >正文

广西建设科技协会网站丽水网站建设哪家好

广西建设科技协会网站,丽水网站建设哪家好,装修网站官网,网站的底部导航栏怎么做最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书#xff0c;我重点关注了TCP协议相关的内容#xff0c;结合自己后台开发的经验#xff0c;写下这篇文章#xff0c;一方面是为了帮助有需要的人#xff0c;更重要的是方便自己整理思路#xff0c;加…最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书我重点关注了TCP协议相关的内容结合自己后台开发的经验写下这篇文章一方面是为了帮助有需要的人更重要的是方便自己整理思路加深理解。 理论基础 OSI网络模型 OSI模型是一个七层模型实际工程中层次的划分没有这么细致。一般来说物理层和数据层对应着硬件和设备驱动程序例如网卡和网卡驱动。传输层和网络层由操作系统内核实现当用户进程需要通过网络传输数据通过系统调用的方式让内核将数据封装为相应的协议格式进而调用网卡驱动传输数据。顶上三层对应具体的网络应用协议FTP、HTTP等这些应用层协议不需要知道具体的通信细节。 传输层 在实际工程中我们常用的应用层服务例如HTTP服务、数据库服务、缓存服务通信的直接底层就是传输层下图是一些常用命令涉及的通信协议。 IPv4Internet Protocol version 4全称是网际协议版本4它使用32地址平时常说的IP协议就是指IPv4类似于192.168.99.100的地址可以看成4位256进制数据也就是32网络地址。但随着网络设备爆炸式增长32地址面临这用完的风险IPv6Internet Protocol version 6应运而生。IPv6使用128位地址但IPv4地址耗尽的问题有了新的解决方案目前普遍使用的还是IPv4IPv6全面取代IPv4还有很长的距离。 UDP User Datagram Protocol全称用户数据报协议。UDP提供面向无连接的服务客户端和服务端不存在任何长期的关系。UDP不提供可靠的通信它不保证数据报一定送达也不保证数据包送达的先后顺序也不保证每份数据报只送达一次。虽然UDP可靠性差但是消耗资源少适用在网络环境较好的局域网中例如不需要精确统计的监控服务eg Statsd。由于使用了UDP客户端每次打点统计只需要一次发送UDP数据报的IO开销服务性能损失很小而且在内网环境数据包一般都能正常到达服务端也能保证较高的可行度。 TCPTransmission Control Protocl全称传输控制协议。和UDP相反TCP提供了面向连接的服务而且提供了可靠性保障。平常我们使用的应用层协议例如HTTPFTP等几乎都是建立在TCP协议之上深入了解TCP的细节对于开发高质量的后台开发和客户端开发都有很好的借鉴意义。下面开始重点介绍TCP协议的细节。 TCP协议 状态转换 为了提供可靠的通信服务TCP通过三次分节建立连接四次分节关闭连接心跳检查判断连接是否正常因此需要记录连接的状态TCP一共定义了11种不同的状态。 通过netstat命令可以查看所有的tcp状态。 三路握手 在三路握手之前服务器必须准备好接收外来的连接。这通常通过调用bind和listen完成被动打开此时服务进程有一个套接字处于LISTEN状态。在客户端发通过调用connect送一个SYN分节后服务进程必须确认ACK此分节同时也发送一个SYN分节这两步在同一分节中完成通过上面的转台扭转图可以知道服务进程中会生成一个处于SYN_RCVD状态的套接字。当再次收到客户端的ACK分节后服务端的套接字状态转变为ESTABLISHED。 客户端通过connect函数发起主动打开在此之前客户端套接字状态为CLOSED。调用connect导致客户TCP发送一个SYN分节此时套接字状态有CLOSED变为SYN_SENT在收到服务器的SYN和ACK后客户端socket再发送ACK分节套接字状态变为ESTABLISHED此时connect返回。 备注SYN分节中除了有序列号之外还会有最大分节大小、窗口规模选项、时间戳等TCP参数具体可以参考协议详细规定。 终止连接 上图展示了客户端执行主动关闭的情形实际上无论客户端还是服务器都可以执行主动关闭。一般情况下客户端执行主动关闭较多所以使用客户端主动关闭为例讲解。 客户端调用close执行主动关闭时发送FIN分节此时客户端套接字状态由ESTABLISED变为FIN_WAIT_1。服务器收到这个FIN会执行被动关闭并向客户端发送ACKFIN的接受也作为一个文件结束符传递给服务进程如果此时服务进程调用套接字的方法无论缓存区是否有数据都会返回EOF服务端套接字状态由ESTABLISED变为为CLOSE_WAIT。客户端接收到ACK后客户端套接字状态由FIN_WAIT_1变为FIN_WAIT_2。 一段时间后当服务进程调用close或者shutdown时也会发生送FIN分节服务端套接字状态由CLOSE_WAIT变为LAST_ACK。客户端在接收到FIN分节后发送ACK分节客户端套接字状态由FIN_WAIT_2变为TIME_WAIT。服务器段接收到客户端的ACK分节状态变成CLOSED。 在某些情况下第二和第三分节可能会合并发送。调用close可能会触发主动关闭当进程正常或者非正常退出时内核会将该进程所使用的文件描述符对应的打开次数执行减一操作当某个文件打开次数为0时也就是说所有的进程都没有使用此文件时也会触发TCP的主动关闭操作。 TIME_WAIT状态 在终止连接的过程中主动关闭方套接字最终的状态是TIME_WAIT在经过2MSLmaximun segment lifetime每个IP数据报都包含一个跳限的字段表明数据报能经过的路由最大个数因此默认每个数据报在因特网中有一个最大存活时间时间后状态才变为CLOSED为什么这样设计呢 这样的设计出于两个考虑 可靠地实现TCP全双工连接的终止。上图的四次分节关闭连接是在正常流程实际情况中任何一次分节都可能出现发送失败的情况。主动关闭方最后的一个ACK分节可能会因为路由问题发送失败为了保证可靠性需要重新发送保证另一方正确关闭套接字因此此时的状态不能为CLOSED。允许老的重复分界在网络中消失。加入10.10.89.9的3400端口和206.168.12.12的80端口建立了一个TCP连接此连接中断后之前发送的TCP分节可能因为路由循环的问题还在因特网中游荡而此时这两个机器相同的端口再建立起新的连接后原来在网络中游荡的分解会对新的连接造成干扰。为了避免这种情况设置一个2MSL的超时时间保证之前还在网络中游荡的数据包完全消失。 套接字编程 下图是C语言的套接字函数考虑Python的socket库只是底层C库的简单封装接口参数大同小异而且Python方便上手调试语法上也更通俗易懂所以本文使用Python的socket库作为讲解实例。 socket socket是python套接字类通过构造函数生成套接字对象构造函数签名如下 其中family参数指协议族type参数指套接字类型protocol值协议类型或者设置为0以选择所给定family和type组合的系统默认值fileno指文件描述符我从来没用过。 family说明AF_INETIPv4协议AF_INET6IPv6协议AF_LOCALUnix域协议AF_ROUTE路由套接字AF_KEY密钥套接字 type说明SOCK_STREAM字节流套接字SOCK_DGRAM数据包套接字SOCK_SEQPACKET有序分组套接字SOCK_RAW原始套接字 protocol说明IPPROTO_TCPTCP传输协议IPPROTO_UDPUDP传输协议 并非所有套接字family和type的组合都是有效的下表给出了一些有效的组合和对应的协议其中标是的项也是有效的但是没有找到便捷的缩略词而空白项是无效组合。 connect connect用于客户端和服务器建立连接函数签名如下 客户端在调用connect之前不必非得调用bind函数内核会确定源IP地址并选择一个临时端口作为源端口。如果使用TCP协议connect将激发TCP的三路握手过程TCP状态由CLOSED变为SYN_SENT最终变为ESTABLISHED在三路握手的过程中可能会出现下面几种情况导致connect报错。connect失败则套接字不可用必须关闭不能对这样的套接字再次调connect函数。 TCP客户端没有是收到SYN分节响应一般发生在服务端backlog队列已满的情况下服务器会对收到的SYN分节不做任何处理。客户端等待一段时间后会重新发送SYN分节直到等待时间超过上限才会抛出ETIMEDOUT错误对应的python异常是TimeoutError。对客户端SYN的响应是RST表明服务端在指定的端口上没有进程在等待与之连接客户端马上会抛出ECONNRFUSED错误。下图是用python连接一个未使用的端口抛出异常ConnectionRefusedError该异常错误号码111errno中查找正是ECONNRFUSED对应的错误码。如果发出的SYN在中间的吗某个路由器上引发了目的地不可达错误客户端会等待一段时间后重新发送直到等待时间超过上限和第一种情况类似此时会抛出ENETUNREACH或者EHOSTUNREACH错误。下图为关闭本机网络后用python调用connect由于网络不可达异常的错误码为101errno中查找正是ENETUNREACH错误码。bind bind方法把一个本地协议地址赋予给一个套接字方法签名如下 在不调用bind的情况下内核会确定IP地址并分配临时端口这种情况很适合客户端因此客户端在调用connect之前不调用bind方法。而服务端需要一个确定的ip和端口因此需要调用bind指定地址和端口。一般情况下服务器都有多个ip地址除了环路地址127.0.0.1外还有局域网和公网地址如果bind绑定的是环路地址127.0.0.1则只有本机通过环路地址才能访问如果需要通过任一ip地址都能访问到可以绑定通配地址0.0.0.0。当指定的端口为0时内核会分配一个临时端口。 如果端口已经在使用会抛出EADDRINUSEerrno对应错误码是98异常可以通过设置SO_REUSEADDR和SO_REUSEPORT这两个套接字参数让多个进程使用同一个TCP连接。 listen 当创建一个套接字时默认为主动套接字也就是说是一个将调用connect发起连接的客户套接字。listen方法把一个未连接的套接字转换为一个被动套接字指示内核应接受指向该套接字的状态请求。根据TCP状态转换图调用listen导致套接字从CLOSED状态转换到LISTEN状态。此方法参数规定了内核应该为相应套接字排队的最大连接个数在bind之后并在accept之前调用。 为了理解backlog参数我们必须认识到内核为其中任何一个给定的监听套接字维护两个队列 未完成连接队列每个这样的SYN分节对应其中一项已由某个客户发出并到达服务器而服务器正在等待完成相应的TCP三路握手过程这些套接字处于SYN_RCVD状态。已完成连接队列每个已完成TCP三路握手过程的客户对应其中一项这些套接字处于ESTABLISHED状态。RTT指的是未连接队列中的任何一项在队列中的存活时间。linux下的backlog指的是已完成连接队列的容量如果服务器长时间未调用accept从此队列中取走数据当新的客户端通过三路握手重新建立连接时服务器不会处理收到的SYN分节而客户端会一直等待并不断重试直到超时。在服务器负载很大的情况下就会造成客户端连接时间长所以需要合理设置backlog大小。 accept accept用于从已完成连接队列头返回下一个已完成连接如果已完成连接队列为空那么进程会被投入睡眠套接字为阻塞方式。 accept会自动生成一个全新的文件描述符代表与所返回客户的TCP连接。需要注意的是此处有两个套接字对象一个是监听套接字一个返回的已连接套接字。区分这两个套接字很重要一个服务器通常仅仅创建一个监听套接字它在该服务器的生命周期内一直存在内核为每个由服务器进程接受的客户连接创建一个已连接套接字也就是说TCP三路握手已经完成当服务器完成对某个给定客户的服务时相应的已连接套接字会被关闭。 close close方法用来关闭套接字方法签名如下 需要注意的是close方法并不一定会触发TCP的四分组连接终止序列当一个已连接套接字被多个进程打开时关闭套接字只会导致此进程相应描述符的计数值减1只有所有进程都将该套接字关闭后套接字的引用计数值小于1以后系统内核才会开始终止连接操作这一点在多进程开发过程中需要格外注意。如果确实想在某个TCP连接上发送FIN触发主动关闭可以调用shutdown方法。 send send方法用于TCP发送数据方法签名如下 每一个TCP套接字都有一个发送缓冲区默认大小通过socket.SO_SNDBUF查看当某个进程调用send时内核从该应用进程的缓冲区复制所有数据到所写套接字的发送缓冲区如果该套接字的发送缓冲区容不下该应用进程的所有数据或是应用进程的缓冲区大小大于套接字的发送缓冲区或是套接字的发送缓冲区已有其他数据该应用进程将被投入睡眠套接字阻塞的情况内核将不从系统调用返回直到应用进程缓冲区的所有数据都复制到套接字发送缓存区。当对端确认收到数据后会发送ACK分节随着对端ACK的不断到达本端TCP才能从套接字发送缓存区中丢弃已确认的数据。 在类似于HTTP的应用层协议中客户端在发送完请求数据之后可以调用s.shutdown(socket.SHUT_WR)告诉服务端所有的数据已经发送完成服务端通过recv会读取到空字符串之后就可以处理请求数据了。 recv recv方法用于TCP接收数据方法签名如下 每一个TCP套接字也都有一个接受缓存区默认大小通过socket.SO_RCVBUF查看。当某个进程调用recv而且缓存区没有数据时该进程会被投入睡眠套接字阻塞的情况内核将不从系统调用返回。 在《Unix网络编程》中所有C语言调用acceptread write函数都会检查errno是否等于EINTR这是因为进程在执行这些系统调用的时候可能会被信号打断导致系统调用返回。而我自己用python2.7尝试的时候发现并没有此问题猜测是python针对系统调用被信号打断的情况。 IO多路复用 在做服务器开发的时候经常会碰到处理多个套接字的情形此时可以通过多进程或这多线程的模型解决此问题。用一个主进程或者主线程负责监听套接字其它每个进程或线程负责一个已连接套接字这样还可以利用操作系统的线程切换实现多并发提高机器利用率。但是机器资源有限不可能无限制的生成新线程或进程IO多路复用应运而生。当内核一旦发现进程指定的一个或者多个IO条件就绪它就通知进程。 IO模型 Unix下有5中IO模型 阻塞式IO非阻塞式IOIO复用信号驱动IO异步IO 已读取数据为例讲解这物种IO模型的区别。每次读取数据包括以下两个阶段而这五种模型的不同之处也体现在这两个阶段不同的处理。 等待数据准备好从内核想进程复制数据 阻塞式IO socket套接字默认就是阻塞式IO。以recvfrom为例用户进程通过系统调用获取TCP数据如果套接字缓存区没有数据系统调用不会返回造成用户进程一直阻塞。直到缓存区有可用数据内核将缓存区数据拷贝至用户进程空间系统调用才会返回。 非阻塞式IO python可以通过调用s.setblocking(False)或者s.settimeout(0.0)将一个套接字设置为非阻塞式IO。以recvfrom为例当没有可用的数据时用户进程不会阻塞而是马上抛出EWOULDBLOCK错误或者EAGAIN对应的errno错误码都是11只有当数据复制到内核空间后才会正确返回数据。 IO多路复用 在有多个IO操作时先阻塞于select调用等待数据报套接字变为可读然后再通过recvfrom把缓存区数据复制到用户进程空间。和阻塞是IO相比当处理的套接字个数较少的时候多路复其实没有性能上的优势它的优势在于可以方便操作很多套接字。 信号驱动式IO 通过信号处理的方式读取数据。 异步IO 当数据包被复制到用户进程后用户通过callback的方式获取数据。 模型对比 可以发现前四种IO模型——阻塞式IO、非阻塞式IO、IO复用、信号驱动IO都是同步IO模型因为真正的IO操作recvfrom将阻塞进程只有异步IO模型才不会导致用户进程阻塞。 python使用 较早的时候使用的多路复用是select函数但是由于时间复杂度较高很快就被其他的函数替代linux下的epollunix下的kqueuewindows下的iocp。为了屏蔽不同系统下的不同实现跨平台的第三方库出现libuv、libev、libevent等这些库根据平台的不同调用不同的底层代码。 如果想直接使用底层的epoll或者select它们封装在python的select库中libuv、libev都有相应的python封装库名叫做pyuv、pyev通过pip安装后即可使用。 python示例 一般情况下为了提升服务的承载量都会采用进程IO多路复用或者线程IO多路复用的开发模式。IO多路复用是为了一个并发单位管理多个套接字而多进程或者多线程是为了充分利用多核。由于GIL的存在python多线程模型并不能充分多核因此我们常见的wsgi server例如gunicorn、uwsgi、tornado等都是使用的多进程IO多路服用开发模式。 tornado使用epoll管理多个套接字gunicorn和uwsgi都可以使用geventgevent是一个python网络库用greenlet做协程切换每个协程管理一个套接字主协程通过libevent轮询查找可用的套接字。因为gevent可以通过monkey patch将socket设置为非阻塞模式因此当服务器有数据库、缓存或者其他网络请求的时候相比tornadouwsgi和gunicorn可以充分利用这部分的阻塞时间。和gunicorn相比uwsgi是c语言实现直观感觉这三个server的性能应该是uwsgi gunicorn tornado和网上的benchmark大致匹配。 | |50|100|150|200|250|300|350|400|450| |---|---|---|---|---|---|---|---|---|---|---| | libev| 92| 181| 269.9| 355.2| 362.6| 367.1| 373.8| 378.5| 315(3%)| | thread| 88.9| 180.5| 266.1| 354.8| 428.9| 460.2| 486.5(2%)| 477.9(7%)| 486.5(22%)| 横坐标是连接个数纵坐标是qps括号内的数字表示错误率。在连接数较少的情况下使用libev管理socket和多线程性能相差不大在连接数超过200后libev模型的请求耗时会增加导致qps增加的并不多但是线程模型在连接数很多的情况下会导致部分请求一直得不到处理在连接个数350的时候就会出现部分请求超时而libev模型在450的时候才会出现。
http://www.dnsts.com.cn/news/211366.html

相关文章:

  • 免费做电子书的网站有哪些2019建设银行招聘网站
  • 网站 做英文 翻译 规则山东省建筑工程信息网
  • nas做流媒体网站免费建站优化
  • 仙桃网站网站建设wordpress文章如何备份
  • wordpress免费网站模板下载做包装的网站有哪些
  • 网站建设性能分析seo工作室
  • 阿里云备案网站备案网站建设方案书 阿里云
  • 电影网站制作东莞网站建设推广公司哪家好
  • 做公司网站要多久广安 网站建设
  • 怎么拥有网站的所有权西安网站建设动力无限
  • 乌当区城乡建设局网站ui网页设计课程总结
  • 北京商标注册seo的优化流程
  • 网站包括哪些内容一条视频可以多平台发布吗
  • 大理市建设局网站物理结构网站
  • 网站建设合同的要素及签订注意事项专门做餐饮空间设计的网站
  • 如何建设一个简易网站wordpress超级排版器插件
  • 旅游网站制作内容宝塔做网站可以用什么端口
  • 网站seo优化技巧ui设计师找工作
  • 陆金所网站开发二部青岛网站设计建立公司
  • 浙江交工宏途交通建设有限公司网站6关键词林俊杰mp3
  • 团购手机网站怎么做个人如何做商城网站
  • 做个网页需要多少钱优化方案物理必修一答案
  • qq群网站制作关于动漫网站建设规划表
  • 男女生做内个的网站怎么查自己是不是备案人员
  • 交通建设监理协会网站京东联盟怎么做网站
  • 重庆网站制水果网站模版
  • 网站开发预算电商平台怎么注册
  • 旅游网站定位织梦末班和dw建设网站哪个方便优化
  • 海丰县网站设计长治百度贴吧官网
  • 丹阳网站建设效果大学生网站设计作业动画