转 http://taohui.org.cn/tcpperf1.html  陶辉 taohui.org.cn

回到应用层,往往只需要调用类似于accept的API就可以建立TCP连接。建立连接的流程大家都了解--三次握手,它如何与accept交互呢?下面以一个不太精确却通俗易懂的图来说明之:

研究过backlog含义的朋友都很容易理解上图。这两个队列是内核实现的,当服务器绑定、监听了某个端口后,这个端口的SYN队列和ACCEPT队列就建立好了。客户端使用connect向服务器发起TCP连接,当图中1.1步骤客户端的SYN包到达了服务器后,内核会把这一信息放到SYN队列(即未完成握手队列)中,同时回一个SYN+ACK包给客户端。一段时间后,在较中2.1步骤中客户端再次发来了针对服务器SYN包的ACK网络分组时,内核会把连接从SYN队列中取出,再把这个连接放到ACCEPT队列(即已完成握手队列)中。而服务器在第3步调用accept时,其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字而已。

现有我们可以来讨论应用层组件:为何有的应用服务器进程中,会单独使用1个线程,只调用accept方法来建立连接,例如tomcat;有的应用服务器进程中,却用1个线程做所有的事,包括accept获取新连接。

原因在于:首先,SYN队列和ACCEPT队列都不是无限长度的,它们的长度限制与调用listen监听某个地址端口时传递的backlog参数有关。既然队列长度是一个值,那么,队列会满吗?当然会,如果上图中第1步执行的速度大于第2步执行的速度,SYN队列就会不断增大直到队列满;如果第2步执行的速度远大于第3步执行的速度,ACCEPT队列同样会达到上限。第1、2步不是应用程序可控的,但第3步却是应用程序的行为,假设进程中调用accept获取新连接的代码段长期得不到执行,例如获取不到锁、IO阻塞等。

那么,这两个队列满了后,新的请求到达了又将发生什么?

若SYN队列满,则会直接丢弃请求,即新的SYN网络分组会被丢弃;如果ACCEPT队列满,则不会导致放弃连接,也不会把连接从SYN列队中移出,这会加剧SYN队列的增长alt。所以,对应用服务器来说,如果ACCEPT队列中有已经建立好的TCP连接,却没有及时的把它取出来,这样,一旦导致两个队列满了后,就会使客户端不能再建立新连接,引发严重问题。

所以,如TOMCAT等服务器会使用独立的线程,只做accept获取连接这一件事,以防止不能及时的去accept获取连接。

那么,为什么如Nginx等一些服务器,在一个线程内做accept的同时,还会做其他IO等操作呢?

这里就带出阻塞和非阻塞的概念。应用程序可以把listen时设置的套接字设为非阻塞模式(默认为阻塞模式),这两种模式会导致accept方法有不同的行为。对阻塞套接字,accept行为如下图:

这幅图中可以看到,阻塞套接字上使用accept,第一个阶段是等待ACCEPT队列不为空的阶段,它耗时不定,由客户端是否向自己发起了TCP请求而定,可能会耗时很长。 对非阻塞套接字,accept会有两种返回,如下图:

由 http://www.cnblogs.com/diegodu/p/3977739.html 可知,无论是阻塞还是非阻塞都是同步的,因为都要阻塞在从内核考到应用程序的过程上。

非阻塞套接字上的accept,不存在等待ACCEPT队列不为空的阶段,它要么返回成功并拿到建立好的连接,要么返回失败。

所以,企业级的服务器进程中,若某一线程既使用accept获取新连接,又继续在这个连接上读、写字符流,那么,这个连接对应的套接字通常要设为非阻塞。原因如上图,调用accept时不会长期占用所属线程的CPU时间片,使得线程能够及时的做其他工作。

高性能网络编程1----accept建立连接相关推荐

  1. 高性能网络编程(一)----accept建立连接

    最近在部门内做了个高性能网络编程的培训,近日整理了下PPT,欲写成一系列文章从应用角度谈谈它. 编写服务器时,许多程序员习惯于使用高层次的组件.中间件(例如OO(面向对象)层层封装过的开源组件),相比 ...

  2. 高性能网络编程(一)----accept建立连接(陶辉)

    http://blog.csdn.net/russell_tao/article/details/9111769 最近在部门内做了个高性能网络编程的培训,近日整理了下PPT,欲写成一系列文章从应用角度 ...

  3. 高性能网络编程(1)—accept建立连接‍(转载,作者:陶辉)

    编 写服务器时,许多程序员习惯于使用高层次的组件.中间件(例如OO(面向对象)层层封装过的开源组件),相比于服务器的运行效率而言,他们更关注程序开发 的效率,追求更快的完成项目功能点.希望应用代码完全 ...

  4. 高性能网络编程--陶辉

    1       高性能网络编程1-accept建立连接 编写服务器时,许多程序员习惯于使用高层次的组件.中间件(例如OO(面向对象)层层封装过的开源组件),相比于服务器的运行效率而言,他们更关注程序开 ...

  5. 高性能网络编程总结及《TCP/IP Sockets编程(C语言实现) (第2版)》 代码下载(链接以及文件打包)

    http://blog.csdn.net/column/details/high-perf-network.html http://blog.csdn.net/russell_tao/article/ ...

  6. 高性能网络编程7--tcp连接的内存使用

    当服务器的并发TCP连接数以十万计时,我们就会对一个TCP连接在操作系统内核上消耗的内存多少感兴趣.socket编程方法提供了SO_SNDBUF.SO_RCVBUF这样的接口来设置连接的读写缓存,li ...

  7. 高性能网络编程(七)TCP连接的内存使用

    当服务器的并发TCP连接数以十万计时,我们就会对一个TCP连接在操作系统内核上消耗的内存多少感兴趣.socket编程方法提供了SO_SNDBUF.SO_RCVBUF这样的接口来设置连接的读写缓存,li ...

  8. 27.Linux网络编程 掌握三次握手建立连接过程掌握四次握手关闭连接的过程掌握滑动窗口的概念掌握错误处理函数封装实现多进程并发服务器实现多线程并发服务器

    基本概念叫协议 什么叫协议? 协议是一个大家共同遵守的一个规则, 那么在这个网络通信当中,其实就是双方通信和解释数据的一个规则,这个概念 你也不用记,你只要心里明白就可以了, 分层模型, 物数网传会表 ...

  9. 西门子smartclient怎么用_基于Snap7使用C#编程访问西门子PLC系列教程(3)-Snap7Client(建立连接)...

    本文是Snap7软件包系列教程的第3篇. 在上一篇文章中,我们介绍了S7通信协议中有三种角色:客户端/服务器/伙伴:有两种通信模式:客户端/服务器(Client/Server)模式和伙伴/伙伴(Par ...

最新文章

  1. FlameScope 更高级全面的火焰图
  2. nginx+tomcat+memcache实现负载均衡、session共享
  3. mysql存储过程打不开了_请问mysql存储过程的问题,我找了几个例子一个都运行不起来,...
  4. SET ARITHABORT ON 对UI的影响
  5. UI设计素材模板|表单的临摹学习技巧
  6. anaconda python_Anaconda下Python环境下载及安装
  7. 自定义数据库连接池和Druid介绍
  8. ps mysql进程_ps(Process Status)进程状态:列出当前正在运行的进程
  9. 笔记本电池不充电了 无法充电 如何激活
  10. DTCMS网站开发遇到的一些问题
  11. RuntimeError: Error compiling objects for extension 和nvcc fatal : Unsupported gpu architecture ‘c
  12. STM32 Flash读写;Flash地址对应的存储内容及方式;
  13. 你的知识需要管理PKM
  14. Eclipse 工具上Springboot项目的简单 增删改查 的搭建
  15. 联想天逸 510S 2022怎么样
  16. Swift MD5加密
  17. 2023年微信公众号留言功能怎么开启?公众号留言功能怎么开通
  18. vi/vim 中可以使用 :s 命令来替换字符串。
  19. linux命令行怎么播放,在linux命令行里能听歌看电影吗
  20. Linux下Java剪贴板的访问

热门文章

  1. 分布式消息技术 Kafka
  2. 剑指Offer Ⅱ 003.二进制加法(力扣剑指Offer专项突击版——整数_3)
  3. SpringBoot定时任务@EnableScheduling
  4. 2021-04-14 Matlab实现模糊聚类分析 FCM
  5. 使用python操作postgresql 查询
  6. oracle sys 查询语句,Oracle EBS-SQL (SYS-7):表单个性化查询.sql
  7. mysql not in优化_MySQL性能优化 — 实践篇2
  8. 怎样在线把别人web前端代码抓下_自学web前端8个月,我是怎样拿下7K薪资的?
  9. Java数据结构和算法(八)——递归
  10. Java NIO浅析