smw*_*dia 55 http websocket spring-websocket
根据这里:
HTTP Upgrade标头请求服务器将应用层协议从HTTP切换到WebSocket协议.
客户端握手在IE10和服务器之间建立了HTTP-on-TCP连接.在服务器返回其101响应之后,应用层协议从HTTP切换到使用先前建立的TCP连接的WebSockets.
此时HTTP完全脱离了图片.使用轻量级WebSocket线协议,任何端点现在都可以随时发送或接收消息.
所以,我的理解是,在第一个客户端完成与服务器的握手后,服务器的80端口将被WebSocket协议垄断.并且HTTP不再在80端口上运行.
那么第二个客户端如何与服务器交换握手.所有WebSocket握手都是HTTP格式.
谢谢你到目前为止的所有答案.他们真的很有帮助.
现在我明白同一台服务器的80端口是由多个连接共享的TCP.这种共享完全没问题,因为TCP连接是由5元素元组标识Jan-Philip Gehrcke出来的.
我想补充几点想法.
这两个WebSocket和HTTP仅仅是应用层协议.通常他们都依赖TCP协议作为他们的运输.
WebSocket设计有意为握手和后续通信选择服务器的端口80 .我认为设计人员希望从传输级别的角度看 WebSocket通信看起来像普通的HTTP通信(即服务器端口号仍然是80).但根据jfriend00答案,这个技巧并不总是欺骗网络基础设施.
来自RFC 6455 - WebSocket协议
基本上,考虑到Web的限制,它应尽可能地将原始TCP暴露给脚本.它的设计也使其服务器可以与HTTP服务器共享一个端口,使其握手成为有效的HTTP升级请求.可以在概念上使用其他协议来建立客户端 - 服务器消息传递,但WebSockets的目的是提供一个相对简单的协议,该协议可以与HTTP和部署的HTTP基础结构(例如代理)共存,并且尽可能安全地接近TCP.在给定安全性考虑的情况下使用此类基础结构,通过有针对性的添加来简化使用并简化简单事务(例如添加消息语义).
所以我认为我在下面的陈述中错了:
握手请求模仿 HTTP请求,但后面的通信没有.握手请求到达端口80上的服务器. 由于它是80端口,服务器将使用HTTP协议对其进行处理.这就是为什么WebSocket握手请求必须是HTTP格式的原因. 如果是这样,我认为必须修改/扩展HTTP协议以识别那些特定于WebSocket的东西.否则它将无法实现它应该屈服于 WebSocket协议.
我认为应该这样理解:
WebSocket通信以从客户端到服务器的有效 HTTP请求开始.因此,服务器遵循HTTP协议来解析握手请求并识别协议变更的请求.它是切换协议的服务器.所以HTTP协议不需要改变.HTTP协议甚至不需要了解WebSocket.
因此,WebSocket与Comet技术的不同之处在于,WebSoket并不局限于当前的HTTP领域以解决双向通信问题.
Jan*_*cke 68
其他答案已经有所帮助.我想指出你的问题是一个非常好的问题,并希望从涉及listen()和的角度来回答它accept().这两个系统调用的行为应足以回答您的问题.
对于问题的核心部分,根据HTTP或WebSocket确实没有区别:共同点是TCP over IP,这足以回答你的问题.不过,你应该得到的WebSocket的是如何与TCP一个答案(我试图阐述的是多一点在这里):发送HTTP请求需要双方之间建立的TCP/IP连接.如果是简单的Web浏览器/ Web服务器方案
在此交换之后,不再需要底层TCP连接,并且通常会被破坏/断开连接.在HTTP升级请求的情况下,底层TCP连接继续生效,并且WebSocket通信通过最初创建的完全相同的TCP连接(上面的步骤(1)).
如您所见,WebSocket和标准HTTP之间的唯一区别是高级协议(从HTTP到WebSocket)中的切换,而不更改底层传输通道(TCP/IP连接).
这是我曾经与自己斗争的一个话题,很多人都不理解.但是,当人们理解操作系统提供的基本套接字相关系统调用是如何工作时,这个概念实际上非常简单.
首先,需要了解IP连接由五条信息唯一定义:
IP:机器A和IP的端口:机器B的端口和协议(TCP或UDP)
现在,通常认为套接字对象代表连接.但这并非完全正确.它们可能代表不同的东西:它们可以是主动的或被动的.被动/聆听模式下的套接字对象做了一些非常特殊的事情,这对回答你的问题非常重要. http://linux.die.net/man/2/listen说:
listen()将sockfd引用的套接字标记为被动套接字,即作为套接字使用accept(2)接受传入的连接请求.
因此,我们可以创建一个侦听传入连接请求的被动套接字.根据定义,这样的套接字永远不能代表连接.它只是监听连接请求.
让我们前往accept()(http://linux.die.net/man/2/accept):
accept()系统调用与基于连接的套接字类型(SOCK_STREAM,SOCK_SEQPACKET)一起使用.它在侦听套接字sockfd的挂起连接队列上提取第一个连接请求,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符.新创建的套接字未处于侦听状态.原始套接字sockfd不受此调用的影响.
这就是我们需要知道的所有内容,以便回答您的问题.accept()不会更改之前创建的被动套接字的状态.它返回一个活动的(连接的)套接字(这样的套接字然后表示上面的五条信息状态 - 简单,对吧?).通常,这个新创建的活动套接字对象然后被切换到另一个进程或线程或只是负责连接的"实体".在accept()返回此连接的套接字对象之后,accept()可以在被动套接字上再次调用,并且一次又一次地调用- 这被称为接受循环.但是电话accept()需要时间,对吧?它不能错过传入的连接请求吗?刚引用的帮助文本中有更多基本信息:有一个挂起的连接请求队列!它由操作系统的TCP/IP堆栈自动处理.这意味着虽然accept()只能一个接一个地处理传入的连接请求,但即使它们以高速率进入或(准)同时也不会丢失传入的请求.可以说,行为accept()是限制机器可以处理的传入连接请求的频率.然而,这是一个快速的系统调用,并且在实践中,其他限制首先出现 - 通常与处理到目前为止已接受的所有连接相关的限制.
jfr*_*d00 20
你似乎在这里缺少相对简单的事情是每个连接到服务器(特别是你的HTTP服务器)创建它自己的套接字然后在该套接字上运行.一个套接字上发生的事情完全独立于当前连接的任何其他套接字上发生的情况.因此,当一个套接字切换到webSocket协议时,这不会改变其他当前或传入套接字连接发生的情况.那些人可以自己决定如何处理它们.
因此,开放套接字可以使用webSocket协议,而其他传入连接可以是常规HTTP请求或创建新webSocket连接的请求.
所以,你可以有这种类型的序列:
因此,在任何时候,服务器仍然接受端口80上的新连接,并且这些新连接可以是常规HTTP请求,也可以是请求升级到webSocket协议的HTTP请求(从而启动webSocket连接).而且,虽然所有这些都在进行,但已经建立的webSocket连接正在使用webSocket协议通过它们自己的套接字进行通信.
webSocket连接和通信方案经过精心设计,具有以下特征:
您的进一步问题的答案:
1)为什么选择80作为默认端口?设计人员是否希望从传输级别的角度使WebSocket通信看起来像普通的HTTP通信?(即服务器端口是好旧的80).
是的,请看我上面的1-4点.webSockets可以通过现有的HTTP通道建立,因此它们通常不需要更改网络基础结构.我想补充一点,即不需要新的服务器或服务器进程,因为现有的HTTP服务器可以简单地添加webSocket支持.
2)我试图描述服务器上协议转换的情况.我想象有不同的软件模块来处理HTTP或WebSocket流量.第一台服务器使用HTTP模块来处理正常的HTTP请求.当它找到升级请求时,它将切换到使用WebSocket模块.
不同的服务器体系结构将以不同方式处理webSocket数据包和HTTP请求之间的划分.在某些情况下,webSocket连接甚至可能被转发到新进程.在其他情况下,它可能只是在同一进程中的一个不同的事件处理程序,它注册了套接字上的传入数据包流量,现在已经切换到webSocket协议.这完全取决于Web服务器体系结构以及它如何选择处理webSocket流量.实现webSocket应用程序服务器端的开发人员很可能会选择与其特定Web服务器体系结构兼容的现有webSocket实现,然后编写在该框架内工作的代码.
在我的例子中,我选择了与node.js一起使用的socket.io库(这是我的服务器架构).该库为我提供了一个对象,该对象支持新连接webSockets的事件,然后是一组用于读取传入消息或发送传出消息的其他事件.初始webSocket连接的详细信息都由库处理,我不必担心任何问题.如果我想在建立连接之前要求身份验证,socket.io库可以让我插入它.然后我可以从任何客户端接收消息,向任何单个客户端发送消息或向所有客户端发送广播信息.我主要使用它进行广播,以便在网页中保留一些"实时"信息,以便网页显示始终是最新的.无论何时服务器上的值发生更改,我都会将新值广播到所有连接的客户端.
回答你的问题:处理到端口80的同步Websocket和HTTP连接......
这意味着:在满意的TCP握手时,监听serviceip:80的服务继续产生一个新的进程或线程,并将该连接的所有通信切换到它(或者通过执行与该事件关联的回调作为异步来提供请求nodejs,正如jfriend00正确指出的那样).
然后等待或处理队列中的下一个传入请求.
如果你想知道HTTP 1.1和UPGRADE请求在所有这些方面发挥了什么作用,这篇关于它的MSDN文章非常清楚:
WebSocket协议有两部分:建立升级连接的握手,然后是实际的数据传输.首先,客户端通过使用"Upgrade:websocket"和"Connection:Upgrade"标头以及一些特定于协议的标头来请求websocket连接,以建立正在使用的版本并设置握手.如果服务器支持该协议,则使用相同的"Upgrade:websocket"和"Connection:Upgrade"标头进行回复并完成握手.握手成功完成后,数据传输开始.
只有Websocket服务通常不会内置到Web服务器中,所以不是真正打算在端口80中侦听,只是通过它可以通过Web服务器的透明转发进行访问.Apache Web服务器使用mod_proxy_wstunnel执行此操作.
当然,您也可以拥有一个内置Web套接字实现的Web服务器:例如Apache Tomcat.
这里的主要内容是:Websocket协议不是HTTP.它有不同的用途.它是一个独立的应用层通信协议,也建立在TCP之上(尽管TCP不是必需的,但是符合Websockets应用层协议要求的传输层协议).
Websocket服务是与Web服务器服务一起运行的PARALLEL服务.
它使用Websocket协议,现代Web浏览器支持该协议,实现接口的客户端部分.
您可以设置或构建Websocket服务,以便在Websocket客户端(通常是Web浏览器)和该服务之间建立持久的非HTTP连接.
主要优点是:Websocket服务可以在需要时向客户端发送消息("你们其中一个好友已经连接!""你的团队只是进了一个目标!"),而不必等待客户端的明确请求进行更新.
您可以使用HTTP 1.1建立持久连接,但HTTP不是用于提供UPON REQUEST的一组资源以外的任何其他连接,然后关闭连接.
直到最近,在所有主流浏览器都支持Websockets之前,您只有两种方法可以在Web应用程序上实现实时更新:
实现AJAX长轮询请求,这是一个痛苦而低效的过程.
使用/构建浏览器插件(例如Java applet支持插件),以便能够与您更新服务建立非HTTP连接,这比长轮询更有效但更痛苦.
就服务的共享侦听端口而言(可以是任何TCP端口,甚至不必对因特网开放,因为大多数Web服务器支持透明转发Web套接字连接),它的工作方式与任何其他TCP完全相同service:服务只是监听它,当TCP握手结束时,存在TCP套接字,服务与客户端通信.
像往常一样,当分配了唯一的client_ip:client_TCP_port对时,将区分对侦听特定TCP套接字的服务的所有连接(server_ip:service_TCP_port),客户端在其可用的TCP端口中随机选择client_TCP_port.
如果您仍然对Websocket连接握手时发生的HTTP-> Websocket应用程序协议切换以及它与底层TCP连接没有任何关系有疑问,我建议您使用Jan-Philip Gehrcke的答案,这很清楚一个有启发性的,可能是你真正想要的.
| 归档时间: |
|
| 查看次数: |
38932 次 |
| 最近记录: |