关于端口共用
以前整Socket编程(VB6.0)有时忘关闭Socket再次启动时就报端口已经被用了,当时的办法就是重启系统,后来看到书上介绍一个端口唯一标识一个应用程序,于是就高兴的认为一个端口只能被一个应用程序绑定,这样和谐的过了一些年,直到有一天发现自己整了一年多的IIS其实可以多个进程(w3p.exe)共用一个80端口,于是俺的世界又不和谐了.
为了解决这一重大矛盾,作为一个2B程序员,我尝试了平行宇宙理论,玄理论,直到上帝造物说...-_",呵呵扯淡了。
下面谈一下本人的YY,大神们看了表笑,还望不吝赐教。
关于链接的回忆
小时候还记的厂里有个总机室,师傅姓王,里面有个电话交换机具体叫什么也不清楚,就是一个合子后面连了很多电话线前面很多插空,这些电话线连到厂里的多个办公室,小王找小李时需要摇下电话打到总机叫王师傅接,王师傅晚上爱打麻将白天经常接错线,接外线貌似要层层转接很麻烦,好在厂里电话主要用来各部门闲聊扯蛋的,(找远方亲戚一般是写信或拍电报)由于大家上班无聊会用电话扯蛋,当时经常占线,小张跟小李正聊到兴头上,现在吴厂张要找小李,但是王师傅说小李正跟小张接着,此时吴厂张发话了,给我拔掉,结果小张那头突然掉线了,而小李突然发现小张怎么变声了.........,当然你可能会想(哥确实想过)为什么不每个部门两两拉根线呢,这样就不要王师傅转接了,不过上完高中后(注意不是初中)哥发现这样一来全国的电话网多少根线都拉不过来,而且就厂里来说,如果有10个部门,需要每个部门都按十个电话。 哥对于连接的理解也就停留在这个水平上,以至一直误解了TCP链接,不过看完本文后您会发现以前的电话是真正意义上的流连接(先不提波粒二象性这事了^_^)
TCP链接应该是幻觉
数字线路的关键是将信息编码后拆成数据包来一份一份发送,因此会有所谓的延迟(编码解码转发等时间),而以前的电话只要接通后就是按光速传播的,呵呵
不管是TCP,还是UDP,都是走IP数据报然后由链路层转物理层发送出去的,对IP层发送数据来说TCP跟UDP没任何区别,TCP的三次握手更是神马,当然话说的有点绝对了,IP层的数据报中有一个协议标识字段,目的是在收到IP数据报后决定将这个数据报交TCP驱动还是UDP驱动来处理。从上面的过程描述可以看出所谓的TCP链接是一个幻觉,其本质应该是TCP驱动程序维护的一个结构体(里面应该有源IP+端口,目标IP+端口,初始序列号,以及上一次收/发数据包的序列号等等字段),而服务端应用程序绑订端口本质是为了TCP驱动在收到TCP数据包时作为路由的标志。
一个服务器端口能同时跟很多浏览器建立TCP链接吗?
一个服务端端口理论上可以建立无限个连接,通过 [Local-IP:Port跟Remote-IP:Port ]组合可以区分每个连接(注意客户端--连接发起端,每次总使用一个未使用的随机端口),但是由于每个链接需要一定的内存空间(包括缓冲窗口),以及TCP驱动程序需要多个线程来维护这些链接(CPU资源),因此实际上不能同时保持很多个TCP连接。
同个端口多个网站怎么收发数据包?
首先发应该不是问题,TCP驱动将数据包在对应的TCP链接上发回去,客户端进程就能正确接收了(TCP客户端不存在端口共用的说法)。
直接是收的问题,在TCP报头上没有特殊的标识的情况(类似cookie的机制,当然正常情况下不应该去改已经存在的TCP协议实现),服务端能做的是在应用层上做处理即引进路由代理,根据种种迹象哥发现这个代理可能叫Http.Sys当然Net.TCP Port Sharing Service也很可疑。
好了在假设这个代理存在后,收数据的过程应该是这样的: 当共享端口的某个TCP链接到数据包后,首先将数据包发给代理(就想TCP以前的作法一样),接着代理根据TCP数据包中的数据具体应该是http协议中的Host报头(即IIS中设置的网站主机头属性),将数据转发给对应主机头的网站(更可行的做法是将该Tcp链接的Socket句柄给对应的网站处理程序),但不管怎么样代理必须要对TCP数据包中的数据段进行分析。
另外Net.TCP也应该在TCP数据报的数据区有额外标的识别,因为我们使用WCF的Net.TCP时,指定服务端点属性其实类似IIS中的主机头设置,当然以上都是YY。。。