socket跟TCP/IP 的关系,单台服务器上的并发TCP连接数可以有多少

常识一:文件句柄限制

在linux下编写网络服务器程序的朋友肯定都知道每一个tcp连接都要占一个文件描述符,一旦这个文件描述符使用完了,新的连接到来返回给我们的错误是“Socket/File:Can'topen so many files”

这时你需要明白操作系统对可以打开的最大文件数的限制。

  • 进程限制

    • 执行ulimit -n 输出1024,说明对于一个进程而言最多只能打开1024个文件,所以你要采用此默认配置最多也就可以并发上千个TCP连接。

    • 临时修改:ulimit -n1000000,但是这种临时修改只对当前登录用户目前的使用环境有效,系统重启或用户退出后就会失效。

    • 永久修改:编辑/etc/security/limits.conf 文件, 修改后内容为

      * soft nofile 1000000

      * hard nofile 1000000

  • 全局限制

    • 执行 cat/proc/sys/fs/file-nr 输出9344 0592026,分别为:1.已经分配的文件句柄数,2.已经分配但没有使用的文件句柄数,3.最大文件句柄数。但在kernel2.6版本中第二项的值总为0,这并不是一个错误,它实际上意味着已经分配的文件描述符无一浪费的都已经被使用了 。

    • 我们可以把这个数值改大些,用 root 权限修改 /etc/sysctl.conf 文件:

      fs.file-max = 1000000

      net.ipv4.ip_conntrack_max = 1000000

      net.ipv4.netfilter.ip_conntrack_max = 1000000

常识二:端口号范围限制?

操作系统上端口号1024以下是系统保留的,从1024-65535是用户使用的。由于每个TCP连接都要占一个端口号,所以我们最多可以有60000多个并发连接。我想有这种错误思路朋友不在少数吧?(其中我过去就一直这么认为)

我们来分析一下吧

  • 如何标识一个TCP连接:系统用一个4四元组来唯一标识一个TCP连接:{local ip, local port,remoteip,remoteport}。好吧,我们拿出《UNIX网络编程:卷一》第四章中对accept的讲解来看看概念性的东西,第二个参数cliaddr代表了客户端的ip地址和端口号。而我们作为服务端实际只使用了bind时这一个端口,说明端口号65535并不是并发量的限制。

  • server最大tcp连接数:server通常固定在某个本地端口上监听,等待client的连接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,即使server端有多个ip,本地监听端口也是独占的,因此server端tcp连接4元组中只有remoteip(也就是client ip)和remoteport(客户端port)是可变的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。


要写网络程序就必须用Socket,这是程序员都知道的。而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,write等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。


对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。对于TCP/IP,我们还知道TCP和UDP,前者可以保证数据的正确和可靠性,后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,很多时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。


我们还知道如下几个事实:

1。一个指定的端口号不能被多个程序共用。比如,如果IIS占用了80端口,那么Apache就不能也用80端口了。

2。很多防火墙只允许特定目标端口的数据包通过。

3。服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。


于是,一个困惑了我很久的问题就产生了。如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?如果是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了--防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接请求和处理方式。我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?


后来,我又仔细研读了TCP/IP的协议栈的原理,对很多概念有了更深刻的认识。比如,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End 

to End)的数据包传送,这里的节点是一台网络设备,比如计算机。因为IP层只负责把数据送到节点,而不能区分上面的不同应用,所以TCP和UDP协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。


所以,我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。


TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!


在Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很相似,实际上在BSD系统里就是跟文件句柄一样存放在一样的进程句柄表里。这个socket其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等等。这些句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定的对象进行操作--这其实是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。


现在我们知道,socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。


现在我们明白,如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的连接建立过程。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。


明白socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系,这很重要!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SSPL的MongoDB再被抛弃,GUN Health也合流PostgreSQL

2019 年 2 月 12 日,红帽官方发博称,Red Hat Satellite 将拥抱PostgreSQL,并且不会支持 SSPL 许可的 MongoDB 新版本。无独有偶,同一天GNU Health也发博称GNU Health Federation Information System 将从MongoDB迁移到PostgreSQL&…

开源的 .NET 数据库迁移框架

你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用!简介FluentMigrator 是一个开源的数据库迁移框架,可以帮助用户在开发过程中保持数据库的一致性。它提供了一个简洁的 Flue…

在deepin上安装YouCompleteMe

详细安装步骤在github上有,https://github.com/Valloric/YouCompleteMe,我这里是自己总结的简化版安装步骤。 步骤1.安装Vundle 首先,clone到本地 git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim把以下内容…

2015年IT领域里Docker和其它颠覆性的趋势

本文讲的是2015年IT领域里Docker和其它颠覆性的趋势,【编者的话】文中作者介绍了2015年IT领域的一些颠覆性的趋势,比如Docker将如何革新PaaS、IaaS等,Docker将如何颠覆虚拟化、私有云、配置管理。 2014年真是令人兴奋的一年,这一年…

进化:从孤胆极客到高效团队_极客狂:为什么这么多的网站无法使用打印样式表?...

进化:从孤胆极客到高效团队It never ceases to amaze me that people have to look for a link or a button that says “Print” on a web page, especially considering there’s a miracle technology that makes that step unnecessary. Sadly almost nobody uses it, even…

Iterator 和 for...of 循环

Iterator 和 for...of 循环 Iterator(遍历器)意义 为Array、Object、Map、Set四种数据集合,提供统一的接口机制来处理所有不同的数据结构 。 任何数据结构,只要部署 Iterator 接口,就可以完成遍历操作(即依…

python简单开发接口

1、首先需要安装flask这个模块:pip install flask。flask是个轻量级的接口开发框架2、开发接口有什么作用  1、mock接口,模拟一些接口,在别的接口没有开发好的时候,需要用mock去模拟一些接口。  2、知道接口是怎么开发的&…

九哥聊Kestrel网络编程第二章:开发一个Fiddler

推荐序之前在.NET 性能优化群内交流时,我们发现很多朋友对于高性能网络框架有需求,需要创建自己的消息服务器、游戏服务器或者物联网网关。但是大多数小伙伴只知道 DotNetty,虽然 DotNetty 是一个非常优秀的网络框架,广泛应用于各…

apple tv 开发_如何跨多台Apple TV同步Apple TV的主屏幕

apple tv 开发If you have more than one Apple TV in your household, you probably know how annoying it is when you have to install Apple TV apps multiple times on each device. However, with the release of tvOS 11, that’s no longer the case. 如果您的家庭中有…

这些故事说的都是你——译者带你读《硅谷革命》

作者 | 薛命灯 作为《硅谷革命》的译者之一,同时也是一个拥有十余年软件开发和架构经验的工程师,当时我在决定是否接受重译这本书的时候,几乎是不假思索地答应了郭蕾(本书重启版发起人之一)的提议,只因他的…

runc容器逃逸漏洞最强后续:应对之策汇总与热点疑问解答

美国时间2019年2月11日晚,runc通过oss-security邮件列表披露了runc容器逃逸漏洞CVE-2019-5736的详情。runc是Docker、CRI-O、Containerd、Kubernetes等底层的容器运行时,此次安全漏洞无可避免地会影响大多数Docker与Kubernetes用户,也因此为整…

OOD之问题空间到解空间—附FP的建模

通常会被问到,什么事OOD,然后大部分人期待的答案比较死板,继承、封装、多态!懂这个的人多的去了,有什么好问?回答出来的人是否拿着Java又去做一些面向过程的勾当? 计算机革命起源于机器&#xf…

com surrogate_什么是“ COM Surrogate”(dllhost.exe),为什么它在我的PC上运行?

com surrogateIf you poke around in your Task Manager, there’s a good chance you’ll see one or more “COM Surrogate” processes running on a Windows PC. These processes have the file name “dllhost.exe”, and are part of the Windows operating system. You’…

云计算时代,互联网金融背后的想象空间

本文讲的是云计算时代,互联网金融背后的想象空间,【IT168评论】阿里巴巴在纽交所的开市钟史无前例的由八位合作伙伴敲响,可见阿里对互联网时代构筑起生态系统的坚持。这其中,由余额宝所敲开的互联网金融热潮的热度持续不减&#x…

JavaScript数据结构与算法——集合

1.集合数据结构 集合是一组无序且唯一(不能重复)的项组成的。这个数据结构使用了和有限集合相同的数学概念。 2.创建集合 function Set() {// 这里使用对象而不是数组来表示集合 // js对象中不允许一个键值指向两个不同属性,也保证了集合中的…

php用两个栈来实现队列

php用两个栈来实现队列 一、总结 我主要的问题是不知道的是题目描述,题目和贵的代码之间的关系,以及返回值 思路:A栈做入队操作,B栈做出队操作,入队的时候元素直接入A,出队的时候判断B栈是否为空&#xff0…

facebook 邀请好友_如何查看紧急情况下您的Facebook朋友是否安全

facebook 邀请好友Facebook’s Safety Check feature lets you check in during an emergency to confirm you’re safe. If you have friends or family in an area that you haven’t heard from, though, you may want to ask them directly. Here’s how to ask someone to…

【您有一封来自阿里云的邀请函】阿里云成都客户服务中心20+职位虚席以待,来吧,成就最好的自己!...

如果你不想辜负这个科技的时代,相信它会因你而不同。如果你不想仅做年度大戏的观众,相信自己会成为主角。如果你不想淹没在枯燥与苟且中,相信工作有诗和远方。那么,不要犹豫,加入我们!在这,你已…

A - A Secret -扩展KMP

题目大意:给你两个字符串A,B,现在要你求B串的后缀在A串中出现的次数和后缀长度的乘积和为多少。题解:扩展KMP模板题,将A和B串都逆序以后就变成了求前缀的问题了,扩展KMP求处从i位置开始的最长公共前缀存于数组。最后通…

.NET 代码优化 聊聊逻辑圈复杂度

本文属于 dotnet 代码优化系列博客。相信大家都对圈复杂度这个概念很是熟悉,本文来和大家聊聊逻辑的圈复杂度。代码优化里面,一个关注的重点在于代码的逻辑复杂度。一段代码的逻辑复杂度越高,那么维护起来的难度也就越大。衡量代码的逻辑复杂…