一、TCP连接与端口

web服务器只开启了一个端口,他是如何为多用户服务的?

问题描述

不同主机之间通讯,必须依赖套接字,而端口号是套接字的标识(开始是这样认为的),那么假设web服务器进程,开启了80端口号(即监听80端口号),接着客户端浏览器,打开任意端口,发起TCP连接请求,服务器80端口监听到请求,建立TCP连接,最后通过客户端套接字和服务器套接字进行通信,那么其他用户怎么办? 80端口也被占用,改如何建立TCP连接?现实中大家发送http请求好像都可以使用一样的端口,如80。

问题解决

首先,明确几点:

1、TCP套接字的唯一标识是一个四元组(源IP地址,源端口号,目的IP地址,目的端口号)

2、TCP创建连接,会进行“三次握手”,

我们这里暂且把TCP建立连接的报文段称为:称为TCP连接

把TCP承载请求数据的报文段称为:TCP请求

客户端浏览器和web服务器的通信过程是这样的:

在建立连接阶段:

浏览器进程打开任意端口,所有的浏览器都是将TCP连接报文,发送给服务器进程监听的端口(如:80),服务器接受到请求,为每个请求创建新的套接字(依据请求报文的源ip,源端口号和自己的ip、端口号)

在发送http请求阶段:

此时连接已经建立,承载了 Http请求信息的TCP请求报文会发送到对应的套接字

因此: 多个不同的套接字可以拥有相同的目的端口号80,由于源ip或端口号不同,TCP套接字就可以唯一标识,通信就可以进行。

同时,一个端口号只能被一个进程所监听

举一反三:其实所有使用TCP的应用程序对的通信都是一样的,分为建立连接和发送数据阶段。

在建立连接时,对于 客户端TCP套接字还没有形成,服务器端进程也是如此,它只是监听80端口而已,把所有目的端口号为80的TCP报文段统统接收,然后去处理,即建立套接字,为套接字分配处理进程。当连接建立时,对应着服务器、客户端套接字的形成,之后的通信,不会将TCP报文段在发送给监听80端口的服务器进程,而是发给与连接对应的套接字,它的目的端口号也是80,但他只是套接字的一部分。

对于服务器进程也是不一样的:一个专门用于建立连接,它监听端口,创建用于连接的套接字

一个专门用于处理请求,通过新建立的套接字发送和接收请求

最好再次总结

1.一个端口同一时间只能bind给一个SOCKET。就是同一时间一个端口只可能有一个监听线程

2.为什么一个端口能建立多个TCP连接,同一个端口也就是说 server ip和server port 是不变的。那么只要[client ip 和 client port]不相同就可以了。能保证接唯一标识[server ip, server port, client ip, client port]的唯一性。

端口号不是套接字的唯一标识。另外,UDP套接字是(目的ip地址,目的端口号),

二、TCP端口(客户端-服务端)

关于TCP服务器最大并发连接数有一种误解就是“因为端口号上限为65535,所以TCP服务器理论上的可承载的最大并发连接数也是65535”。

先说结论:对于TCP服务端进程来说,他可以同时连接的客户端数量并不受限于可用端口号。并发连接数受限于linux可打开文件数,这个数是可以配置的,可以非常大,所以实际上受限于系统性能。

从理论上说,端口号的作用是在网络连接中标识应用层的进程,服务端一般使用众所周知的端口号进行监听,客户端连接时系统自动分配端口号。一个服务端进程服务于n个客户远程进程,只需要能通过ip地址+端口号的组合把他们区分开即可,没有必要占用本机的其他端口号,客户端连接数增加并不会占用服务器端口号,因此端口号并不能限制并发连接数。当然一台机器上端口号数量的上限确实是65536个,因为tcp首部中使用16bit去存储端口号。所以如果说65536影响了连接数,只有一种可能,就是同一台客户端机子上开n个进程去连同一个服务端进程,因为客户端ip是同一个,为了区分出这些连接,只能使用客户端连接的端口号,那么服务端和一个客户端主机之间的tcp连接数理论上线确实是65536。但是,服务端可以连接n多客户端机子呢。

实际上,确实有个限制端口号的配置,就是MaxUserPort,这实际上是一台主机向外连接使用端口数的限制,这个数也可以配置的,可能默认值才5000,实际上对于正常的服务器主机是够用的,因为你是等别人连接进来的,不是要去连接很多不同的其他主机的。当然你的服务器上可能跑了一些转发的服务,这样你就需要对外连接了,如果被限制在这个配置这儿了确实需要改。但是这个MaxUserPort确实和服务器可以承载的来自客户端的并发连接数没有关系。

伴随这个误解的还有另外一个误解,就是accept之后产生的已连接套接字占用了新的端口。这个绝对是错误的,linux内核不会这么写的,因为完全没必要嘛。客户端连接上来之后产生的这个socket fd就是用来区分客户端的,里面会填上客户端的ip和端口作为发包用,来自客户端的包也会使用这个fd去读取。可以试试netstat -ano,然后起一个服务器看下,客户端连上来这后产生的套接字的服务端端口还是监听的端口。

三、HTTP连接

浏览器发送的请求是复用同一个连接吗?

不一定。

发的不同域名,肯定不复用。

发的同域名。若第一个请求与第二个请求并行发送,不复用。

发的同域名,并且是第一个请求完事了才发第二个请求。则看是否有 connection: keep-alive 请求头,没有则不复用。

发的同域名,第一个请求完了后发第二个请求,有 connection: keep-alive 请求头。则复用同一个 TCP 连接。

补充说明

HTTP 1.1 里大概规范了几项提高性能的手段:

持久连接 (keep-alive/persistent connection)

并行连接

Pipelining

持久连接

每一个请求都会重新建立一个 TCP 连接,一旦响应返回,就关闭连接。 而建立一个连接,则需要进行三次握手。HTTP 1.1 出了一个请求头 connection,默认 keep-alive,告诉服务器不关闭 TCP 连接。

并行连接

由于现代网页通常包含了复数个(>=10)资源,而按照默认设定,一个连接中的每一个请求必须等待收到响应后才能发送下一个请求,所以如果复数的资源请求全部在一个连接 one by one 发送给服务器显然会很慢,而为了弥补这一缺陷,浏览器通常会默认开启多个 TCP 连接,然后再根据每个连接的状态在其中依次发送数据请求,而且客户端有权任意关闭超发的连接。各个浏览器允许的并行连接数大致是这样的(From SO):

Firefox 2: 2

Firefox 3+: 6

Opera 9.26: 4

Opera 12: 6

Safari 3: 4

Safari 5: 6

IE 7: 2

IE 8: 6

IE 10: 8

Chrome: 6

由于 TCP 协议本身有慢启动的特征,会随着时间调谐连接的最大速度,因此在现代浏览器中持久连接和并行连接通常是搭配在一起使用的—— 一方面由于持久连接的存在,每个 TCP 连接已经处于调谐后的状态,另一方面持久连接可以避免重新三次握手的开销。

在 Chrome 中,页面初始并行加载一堆静态资源是会最大开 6 个 TCP 连接去并行运作,其后发 Ajax 请求则是复用之前的 TCP 连接。

Pipelining

按照 HTTP 1.1 的描述,还有种可以提升性能的方案是管道化,可以在一个 TCP 连接中并行执行多个请求并返回。

因为这项技术比较复杂,如何能在一个 TCP 中有序的处理所接收到的包,并且不会乱序返回,这在早期没有规范,所以各大浏览器都没有支持此功能,形同鸡肋。

关于 HTTP 2

HTTP 2 为了性能做了不少努力,比如提供了规范以支持连接的多路复用。

如前文所说,在同一个 TCP 连接里面同时发生两个请求响应就不是那么简单。而 HTTP 2 正是提供了这样的规范,可以给数据拆成包,并打上包的顺序标签以供 TCP 能正确认知接收的包的顺序。

所以很多网络优化的知识已经过时

因为“所有的 HTTP 2.0 的请求都在一个 TCP 链接上”,“资源合并减少请求”,比如 CSS Sprites ,多个 JS 文件、CSS 文件合并等手段没有效果,或者说没有必要。

因为“多路复用”,采用“cdn1.cn,cdn2.cn,cdn3.cn,打开多个 TCP 会话,突破浏览器对同一域名的链接数的限制”的手段是没有必要的。因为因为资源都是并行交错发送,且没有限制,不需要额外的多域名并行下载。

因为“服务器推送”,内嵌资源(如base64的图片)的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)

tcp 服务器响应端口,TCP/HTTP连接/Socket/端口相关推荐

  1. jmeter测试TCP服务器/模拟发送TCP请求

    jmeter测试TCP服务器,使用TCP采样器模拟发送TCP请求. TCP采样器:打开一个到指定服务器的TCP / IP连接,然后发送指定文本并等待响应. jmeter模拟发送TCP请求的方法: 1. ...

  2. python tcp服务器_python实现TCP服务器端与客户端的方法详解

    本文实例讲述了python实现TCP服务器端与客户端的方法.分享给大家供大家参考.具体如下: TCP服务器程序(tsTserv.py): from socket import * from time ...

  3. udp和tcp是服务器响应,HTTP,TCP,UDP的理解和使用

    参考资料 http://www.jianshu.com/p/1ae1170b9a9a Android开发进阶 一.Http理解 Http是一种应用层的协议,它基于TCP协议来进行数据传输.HTTP传输 ...

  4. TCP服务器和客户端的创建(socket/socketserver)

    1 本文记录针对python网络编程学习过程中的socket部分进行记录与总结,内容仅仅涉及最粗浅的部分,日后或许会进行更新与扩展. 2 本文涉及的socket数据传输均使用bytes类型,因此在py ...

  5. python tcp服务器_Python 创建TCP服务器的方法

    问题 你想实现一个服务器,通过TCP协议和客户端通信. 解决方案 创建一个TCP服务器的一个简单方法是使用 socketserver 库.例如,下面是一个简单的应答服务器: from socketse ...

  6. 金蝶服务器响应异常,金蝶提示连接金蝶云服务器异常

    金蝶提示连接金蝶云服务器异常 内容精选 换一换 华为云帮助中心,为用户提供产品简介.价格说明.购买指南.用户指南.API参考.最佳实践.常见问题.视频帮助等技术文档,帮助您快速上手使用华为云服务. 云 ...

  7. linux 端口耗尽,短连接以致端口耗尽

    场景回放 A机器的服务请求B机器的服务 短连接请求,动态创建连接端口 A机器服务会主动关闭连接 短时间内高并发请求 A机器的tcpssports被耗尽了 大部分网络连接处time_wait状态 内核配 ...

  8. bsd协议开源框架tcp服务器,搬运RT Thread中BSD Socket实现UDP及TCP例子

    /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * ...

  9. python tcp服务器并发_python tcp并发服务器

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

最新文章

  1. NVIDIA团队:利用神经网络生成极慢视频
  2. Dubbo与SpringBoot整合流程(从实例入手,附代码下载)
  3. 钉钉猛增40倍流量压力,阿里云DBA如何应对?
  4. sqlyog软件的使用
  5. 神马是代码简单的cmd模式,这就是!
  6. javascript乘法和加法_js 大整数加法、乘法、除法
  7. 24 MM配置-采购-配额管理-定义编码范围
  8. python学习与数据挖掘_python机器学习与数据挖掘
  9. 用AndroidStudio和vsCode运行ReactNative项目
  10. IntelliJ IDEA连接mysql
  11. 什么是网站物理结构、逻辑结构
  12. 使用WWWGrep检查你的网站元素安全
  13. 经典C语言从入门到入坑必学最简单的代码
  14. 联机侠控制台JAVA_我的世界MultiMc启动器
  15. 微信小程序PDF下载方案
  16. cadence 旋转快捷键_cadence常用快捷键自己总结
  17. web前端入门到实战:CSS颜色、背景和剪切
  18. HDU 6105 Gameia 树上博弈(思路题)(内附官方题解)
  19. TI高精度实验室-运算放大器-第七节-共模抑制和电源抑制
  20. typescript是什么_为什么不应该害怕TypeScript

热门文章

  1. 路由器的基本配置(一)---路由器的简单连接
  2. 奈奎斯特准则、比特率、波特率、码元……的逻辑链
  3. gin框架06--Multipart/Urlencoded 表单
  4. 如何跳过等待更新,让Windows直接关机
  5. python爬虫不用库获取百家姓
  6. 启明星辰EDR长时间不访问导致拒绝连接的问题
  7. CodeForce 774 div2 A-C,E题解
  8. VMWare Workstation:局域网PC连接虚拟机里的远程桌面或端口
  9. 华为云FusionInsight湖仓一体解决方案的前世今生
  10. Linux 常用日期命令