TCP/HTTP连接/Socket/端口

一、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]的唯一性。

  1. 端口号不是套接字的唯一标识。另外,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的图片)的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)

参考
https://blog.csdn.net/gao_zhennan/article/details/97494480
https://www.jianshu.com/p/4a58761d758f
https://www.cnblogs.com/everlose/p/12779773.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342