websocket socketchannel write和客户端发起的连接是严格一一对应的吗

在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
第一次用websocket,求问,channel和客户端发起的连接是严格一一对应的吗?
或者说是否可以通过channel来唯一标记正在连接中的客户端?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
不是严格的一一对应的关系。。
server可以连接多个client。。根据channel id来区分不同得client
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你看下url会发现是通过频道id来区分的,和楼上的回答一样
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:博客分类:
7.1.1.关闭WebSocket连接
为_关闭WebSocket连接_,端点需关闭底层TCP连接。端点应该使用一个方法完全地关闭TCP连接,以及TLS会话,如果合适,丢弃任何可能已经接收的尾随的字节。当必要时端点可以通过任何可用的手段关闭连接,例如当受到攻击时。
底层TCP连接,在大多数正常情况下,应该首先被服务器关闭,所以它持有TIME_WAIT状态而不是客户端(因为这会防止它在2个报文最大生存时间(2MLS)内重新打开连接,然而当一个新的带有更高的seq number的SYN时没有对应的服务器影响TIME_WAIT连接被立即重新打开)。在异常情况下(例如在一个合理的时间量后没有接收到服务器的TCP Close)客户端可以发起TCP Close。因此,当服务器被指示_关闭WebSocket连接_,它应该立即发起一个TCP Close,且当客户端被知识也这么做时,它应该等待服务器的一个TCP Close。
例如一个如何使用Berkeley socket在C中得到完全地关闭的例子,一端会在socket上以SHUT_WR调用shutdown(),调用recv()直到获得一个指示那个节点也已经执行了一个有序关闭的0返回值,且最终在socket上调用close()方法。
7.1.2.启动WebSocket关闭阶段握手
为了_启动WebSocket关闭阶段握手_,其带有一个状态码(7.4节)/code/和一个可选的关闭原因(7.1.6节)/reason/,一个端点必须按照5.5.1节的描述发送一个Close控制帧,其状态码设置为/code/且其关闭原因设置为/reason/。一旦一个端点已经发送并接收到一个Close控制帧,那个端点应该按照7.1.1节的描述_关闭WebSocket连接_。
7.1.3. WebSocket关闭阶段握手已启动
一旦发送或接收到一个Close控制帧,这就是说,_WebSocket 关闭阶段握手已启动_,且WebSocket连接处于CLOSING状态。
7.1.4. WebSocket已关闭
当底层TCP连接已关闭,这就是说_WebSocket连接已关闭_且WebSocket连接处于CLOSED状态。如果TCP连接在WebSocket关闭阶段我是已经完成后被关闭,WebSocket连接被说成已经_完全地_关闭了。 如果WebSocket连接不能被建立,这就是说,_WebSocket连接关闭了_,但不是_完全的_。
7.1.5.WebSocket连接关闭代码
按照5.5.1和7.4节的定义,一个Close控制帧可以包含一个表示关闭原因的状态码。一个正关闭的WebSocket连接可以同时由两个端点初始化。_WebSocket连接Close Code_定义为包含在由实现该协议的应用接收到的第一个Close控制帧的状态码(7.4节)。如果这个Close控制帧不包含状态码,_WebSocket连接Close Code_被认为是1005。如果_WebSocket连接已经关闭_且端点没有接收到Close状态码(例如可能发生在底层传输连接丢失时),_WebSocket连接Close Code_被认为是1006。
注意:两个端点可以有不一致的_WebSocket连接关闭代码_。例如,如果远程端点发送了一个Close帧,但本地应用还没有从它的socket接收缓冲区中读到包含Close帧的数据,且本地应用独立地决定关闭连接和发送一个Close帧,两个端点都将发送和接收Close帧且将不发送更多的Close帧。每一个端点将看见另一端发送的以_WebSocket连接关闭代码_结束的状态码。例如,在两个端点独立且在大致相同的时间同时_开启WebSocket关闭阶段握手_的情况下,两个端点可以有不一致的_WebSocket连接关闭代码_是可能的。
7.1.6. WebSocket连接关闭原因
按照5.5.1和7.4节的定义,一个控Close控制帧可以包含一个指示关闭原因的状态码,接着是UTF-8编码的数据,上述数据留给断点解释且本协议没有定义。WebSocket连接的关闭可以被任何一个端点初始化,可能同时发生。_WebSocket 连接关闭原因_由跟在包含在实现该协议的应用接收到的第一个Close控制帧状态码(7.4节)后边的UTF-8编码的数据定义。如果Close控制帧中没有这样的数据,_WebSocket连接关闭原因_是空字符串。
注意:按照7.1.5节指出的相同的逻辑,两个端点可以有不一致的_WebSocket连接关闭原因_。
7.1.7.失败WebSocket连接
某些算法和规范要求端点_失败WebSocket连接_。要做到这一点,客户端必须_关闭WebSocket连接_,并可以以适当的方式把问题报告给用户(这将对开发人员非常有用的)。
同样的,为了做到这一点,服务器必须_关闭WebSocket连接_,并应该记录下问题。
如果_已建立的WebSocket连接_在端点需要_失败WebsSocket连接_之前,端点应该在处理_关闭WebSocket连接_之前发送一个带有适当状态码的Close帧(7.4节)。
如果端点认为另一边不太可能收到并处理关闭帧可以省略发送一个关闭帧,因为错误的性质,导致WebSocket连接失败摆在首要位置。端点必须在被指示为_失败WebSocket端点_之后不继续尝试处理来自远程端点的数据(包括响应关闭帧)。
除上边指出的或由应用层指定的(例如,使用WebSocket API的脚本),客户端应该关闭连接。
7.2.异常关闭
7.2.1.客户端发起的关闭
某些算法,尤其在打开阶段握手期间,需要客户端_失败WebSocket连接_。为了做到这一点,客户端必须按照7.1.7节定义的那样_失败WebSocket连接_。
如果在任何时候,底层的传输层连接意外丢失,客户端必须_失败WebSocket连接_。 除上边指出的或由应用层指定的(例如,使用WebSocket API的脚本),客户端应该关闭连接。
7.2.2.服务端发起的关闭
某些算法需要或推荐服务端在打开阶段握手期间_中断WebSocket连接_。为了做到这一点,服务端必须简单地_关闭WebSocket连接_(7.1.1节)。
7.2.3.从异常关闭中恢复
异常关闭可能由任何原因引起。这样的关闭可能是一个瞬时错误导致的,在这种情况下重新连接可能导致一个好的连接和一个重新开始的正常操作。这样的关闭也可能是一个非瞬时问题的导致的,在这种情况下如果每个部署的客户端遇到异常关闭并立即且持续地的尝试重新连接,服务端可能会因为大量的客户端尝试重新连接遇到的拒绝服务攻击。这种情况的最终结果可能是服务不能及时的恢复或恢复是更加困难。
为了避免这个,当客户端遇到本节描述的异常关闭之后尝试重新连接时,应该使用某种形式的补偿。
第一个重新连接尝试应该延迟一个随机的时间量。这种随机延迟的参数的选择留给客户端决定;一个可随机选择的的值在0到5秒是一个合理的初始延迟,不过客户端可以选择不同的间隔由于其选择一个延迟长度基于实现经验和特定的应用。
第一次重新连接尝试失败,随后的重新连接尝试应该延迟递增的时间量,使用的方法如截断二进制指数退避算法。
7.3.正常连接关闭
服务端在需要时可能关闭WebSocket连接。客户端不能随意关闭WebSocket连接。在这两种情况下,端点通过如下过程_开始WebSocket关闭握手_初始化一个关闭(7.1.2节)。
7.4.状态码
当关闭一个已经建立的连接(例如,当在打开阶段握手已经完成后发送一个关闭帧),端点可以表明关闭的原因。由端点解释这个原因,并且端点应该给这个原因采取动作,本规范是没有定义的。本规范定义了一组预定义的状态码,并指定哪些范围可以被扩展、框架和最终应用使用。状态码和任何相关的文本消息是关闭帧的可选的组件。
7.4.1.定义的状态码
当发送关闭帧时端点可以使用如下预定义的状态码。
1000表示正常关闭,意思是建议的连接已经完成了。
1001表示端点“离开”(going away),例如服务器关闭或浏览器导航到其他页面。
1002表示端点因为协议错误而终止连接。
1003表示端点由于它收到了不能接收的数据类型(例如,端点仅理解文本数据,但接收到了二进制消息)而终止连接。
1004 保留。可能在将来定义其具体的含义。
1005是一个保留值,且不能由端点在关闭控制帧中设置此状态码。它被指定用在期待一个用于表示没有状态码是实际存在的状态码的应用中。
1006是一个保留值,且不能由端点在关闭控制帧中设置此状态码。它被指定用在期待一个用于表示连接异常关闭的状态码的应用中。
1007表示端点因为消息中接收到的数据是不符合消息类型而终止连接(比如,文本消息中存在非UTF-8[]数据)。
1008表示端点因为接收到的消息违反其策略而终止连接。这是一个当没有其他合适状态码(例如)或如果需要隐藏策略的具体细节时能被返回的通用状态码。
1009表示端点因接收到的消息对它的处理来说太大而终止连接。
1010表示端点(客户端)因为它期望服务器协商一个或多个扩展,但服务器没有在WebSocket握手响应消息中返回它们而终止连接。 所需要的扩展列表应该出现在关闭帧的/reason/部分。
注意,这个状态码不能被服务器端使用,因为它可以失败WebSocket握手。
1011表示服务器端因为遇到了一个不期望的情况使它无法满足请求而终止连接。
1015是一个保留值,且不能由端点在关闭帧中被设置为状态码。它被指定用在期待一个用于表示连接由于执行TLS握手失败而关闭的状态码的应用中(比如,服务器证书不能验证)。
7.4.2.保留的状态码范围
0-999范围内的状态码不被使用。
范围内的状态码保留给本协议、其未来的修订和一个永久的和现成的公共规范中指定的扩展的定义。
范围内的状态码保留给库、框架和应用使用。这些状态码直接向IANA注册。本规范未定义这些状态码的解释。
范围内的状态码保留用于私有使用且因此不能被注册。这些状态码可以被在WebSocket应用之间的先前的协议使用。本规范未定义这些状态码的解释。
浏览 23261
jinnianshilongnian
浏览量:1750602
浏览量:2171439
浏览量:4378560
浏览量:178707
浏览量:1245965
浏览量:189352
浏览量:3769530
浏览量:457501
浏览量:484259
推荐一个分布式服务架构:http://minglisoft.c ...
推荐一个分布式服务架构:http://minglisoft.c ...
推荐一个企业分布式服务架构:http://minglisoft ...
haoxinren 写道版主,拦截器和过滤器是不同的东西,你这 ...
启动tomcat报错Cannot create Poolabl ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'WebSocket 是什么原理?为什么可以实现持久连接?
我的图书馆
WebSocket 是什么原理?为什么可以实现持久连接?
以下是腾讯云技术社区整理的 ——众所周知,Web应用的通信过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现。这种机制对于信息变化不是特别频繁的应用可以良好支撑,但对于实时要求高、海量并发的应用来说显得捉襟见肘,尤其在当前业界移动互联网蓬勃发展的趋势下,高并发与用户实时响应是Web应用经常面临的问题,比如金融证券的实时信息、Web导航应用中的地理位置获取、社交网络的实时消息推送等。传统的请求-响应模式的Web开发在处理此类业务场景时,通常采用实时通讯方案。比如常见的轮询方案,其原理简单易懂,就是客户端以一定的时间间隔频繁请求的方式向服务器发送请求,来保持客户端和服务器端的数据同步。其问题也很明显:当客户端以固定频率向服务器端发送请求时,服务器端的数据可能并没有更新,带来很多无谓请求,浪费带宽,效率低下。基于Flash,AdobeFlash通过自己的Socket实现完成数据交换,再利用Flash暴露出相应的接口给JavaScript调用,从而达到实时传输目的。此方式比轮询要高效,且因为Flash安装率高,应用场景广泛。然而,移动互联网终端上Flash的支持并不好:IOS系统中无法支持Flash,Android虽然支持Flash但实际的使用效果差强人意,且对移动设备的硬件配置要求较高。2012年Adobe官方宣布不再支持Android4.1+系统,宣告了Flash在移动终端上的死亡。传统的Web模式在处理高并发及实时性需求的时候,会遇到难以逾越的瓶颈,需要一种高效节能的双向通信机制来保证数据的实时传输。在此背景下,基于HTML5规范的、有Web TCP之称的 WebSocket应运而生。早期HTML5并没有形成业界统一的规范,各个浏览器和应用服务器厂商有着各异的类似实现,如IBM的MQTT、Comet开源框架等。直到2014年,HTML5终于尘埃落地,正式落实为实际标准规范,各个应用服务器及浏览器厂商逐步开始统一,在 JavaEE7中也实现了WebSocket协议。至此无论是客户端还是服务端的WebSocket都已完备。用户可以查阅,熟悉新的HTML协议规范及WebSocket支持。WebSocket 机制以下简要介绍一下WebSocket的原理及运行机制。WebSocket是HTML5下一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的。它与HTTP一样通过已建立的TCP连接来传输数据,但是它和HTTP最大不同是:WebSocket是一种双向通信协议。在建立连接后,WebSocket服务器端和客户端都能主动向对方发送或接收数据,就像Socket一样;WebSocket需要像TCP一样,先建立连接,连接成功后才能相互通信。传统HTTP客户端与服务器请求响应模式如下图所示:WebSocket模式客户端与服务器请求响应模式如下图:上图对比可以看出,相对于传统HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似Socket的TCP长连接通讯模式。一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。相比HTTP长连接,WebSocket有以下特点:是真正的全双工方式,建立连接后客户端与服务器端是完全平等的,可以互相主动请求。而HTTP长连接基于HTTP,是传统的客户端对服务器发起请求的模式。HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别所以它需要对服务器和客户端都进行升级才能实现(主流浏览器都已支持HTML5)。此外还有 multiplexing、不同的URL可以复用同一个WebSocket连接等功能。这些都是HTTP长连接不能做到的。下面再通过客户端和服务端交互的报文对比WebSocket通讯与传统HTTP的不同点:在客户端,new WebSocket实例化一个新的WebSocket客户端对象,请求类似 ws://yourdomain:port/path 的服务端WebSocket URL,客户端WebSocket对象会自动解析并识别为WebSocket请求,并连接服务端端口,执行双方握手过程,客户端发送数据格式类似:GET /webfin/websocket/ HTTP/1.1Host: localhostUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==Origin: http://localhost:8080Sec-WebSocket-Version: 13可以看到,客户端发起的WebSocket连接报文类似传统HTTP报文,Upgrade:websocket参数值表明这是WebSocket类型请求,Sec-WebSocket-Key是WebSocket客户端发送的一个 base64编码的密文,要求服务端必须返回一个对应加密的Sec-WebSocket-Accept应答,否则客户端会抛出Error during WebSocket handshake错误,并关闭连接。服务端收到报文后返回的数据格式类似:HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=Sec-WebSocket-Accept的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,HTTP/1.1 101 Switching Protocols表示服务端接受WebSocket协议的客户端连接,经过这样的请求-响应处理后,两端的WebSocket连接握手成功, 后续就可以进行TCP通讯了。用户可以查阅了解WebSocket客户端和服务端更详细的交互数据格式。在开发方面,WebSocket API 也十分简单:只需要实例化 WebSocket,创建连接,然后服务端和客户端就可以相互发送和响应消息。在WebSocket 实现及案例分析部分可以看到详细的 WebSocket API 及代码实现。腾讯云公网有日租类型七层负载均衡转发部分支持Websocket,目前包括英魂之刃、银汉游戏等多家企业已接入使用。当出现不兼容问题时,请修改websocket配置,websocket server不校验下图中圈出的字段:一个使用WebSocket应用于视频的业务思路如下:使用心跳维护websocket链路,探测客户端端的网红/主播是否在线设置负载均衡7层的proxy_read_timeout默认为60s设置心跳为50s,即可长期保持Websocket不断开近期Websocket将开放自定义配置,敬请期待。相关阅读推荐
TA的推荐TA的最新馆藏
喜欢该文的人也喜欢Netty笔记之六:Netty对websocket的支持 - 简书
Netty笔记之六:Netty对websocket的支持
出现的背景
WebSocket是一种规范,是Html5规范的一部分,websocket解决什么问题呢?解决http协议的一些不足。我们知道,http协议是一种无状态的,基于请求响应模式的协议。
网页聊天的程序(基于http协议的),浏览器客户端发送一个数据,服务器接收到这个浏览器数据之后,如何将数据推送给其他的浏览器客户端呢?
这就涉及到服务器的推技术。早年为了实现这种服务器也可以像浏览器客户端推送消息的长连接需求,有很多方案,比如说最常用的采用一种轮询技术,就是客户端每隔一段时间,比如说2s或者3s向服务器发送请求,去请求服务器端是否还有信息没有响应给客户端,有就响应给客户端,当然没有响应就只是一种无用的请求。
这种长轮询技术的缺点有:
1)响应数据不是实时的,在下一次轮询请求的时候才会得到这个响应信息,只能说是准实时,而不是严格意义的实时。
2)大多数轮询请求的空轮询,造成大量的资源带宽的浪费,每次http请求携带了大量无用的头信息,而服务器端其实大多数都不关注这些头信息,而实际大多数情况下这些头信息都远远大于body信息,造成了资源的消耗。
比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。
WebSocket是什么?
WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。WebSocket API也被W3C定为标准。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
websocket的出现就是解决了客户端与服务端的这种长连接问题,这种长连接是真正意义上的长连接。客户端与服务器一旦连接建立双方就是对等的实体,不再区分严格意义的客户端和服务端。长连接只有在初次建立的时候,客户端才会向服务端发送一些请求,这些请求包括请求头和请求体,一旦建立好连接之后,客户端和服务器只会发送数据本身而不需要再去发送请求头信息,这样大量减少了
网络带宽。websocket协议本身是构建在http协议之上的升级协议,客户端首先向服务器端去建立连接,这个连接本身就是http协议只是在头信息中包含了一些websocket协议的相关信息,一旦http连接建立之后,服务器端读到这些websocket协议的相关信息就将此协议升级成websocket协议。websocket协议也可以应用在非浏览器应用,只需要引入相关的websocket库就可以了。
HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。Websocket使用ws或wss的统一资源标志符,类似于HTTPS,其中wss表示在TLS之上的Websocket。如:
ws:///wsapi
较少的控制开销:相对与http请求的头部信息,websocket信息明显减少。
更强的实时性:由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。
保持连接状态。于HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。
netty对websocket协议的支持
浏览器页面向服务器发送消息,服务器将当前消息发送时间反馈给浏览器页面。
import io.netty.bootstrap.ServerB
import io.netty.channel.ChannelF
import io.netty.channel.EventLoopG
import io.netty.channel.nio.NioEventLoopG
import io.netty.channel.socket.nio.NioServerSocketC
import io.netty.handler.logging.LogL
import io.netty.handler.logging.LoggingH
import java.net.InetSocketA
//websocket长连接示例
public class MyServer {
public static void main(String[] args) throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup wokerGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,wokerGroup).channel(NioServerSocketChannel.class)
.handler(new ))
.childHandler(new WebSocketChannelInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8899)).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
wokerGroup.shutdownGracefully();
服务器端初始化连接
import io.netty.channel.ChannelI
import io.netty.channel.ChannelP
import io.netty.channel.socket.SocketC
import io.netty.handler.codec.http.HttpObjectA
import io.netty.handler.codec.http.HttpServerC
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolH
import io.netty.handler.stream.ChunkedWriteH
public class WebSocketChannelInitializer extends ChannelInitializer&SocketChannel&{
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//websocket协议本身是基于http协议的,所以这边也要使用http解编码器
pipeline.addLast(new HttpServerCodec());
//以块的方式来写的处理器
pipeline.addLast(new ChunkedWriteHandler());
//netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
pipeline.addLast(new HttpObjectAggregator(8192));
//ws://server:port/context_path
//ws://localhost:9999/ws
//参数指的是contex_path
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
//websocket定义了传递数据的6中frame类型
pipeline.addLast(new TextWebSocketFrameHandler());
WebSocketServerProtocolHandler:参数是访问路径,这边指定的是ws,服务客户端访问服务器的时候指定的url是:ws://localhost:8899/ws。
它负责websocket握手以及处理控制框架(Close,Ping(心跳检检测request),Pong(心跳检测响应))。 文本和二进制数据帧被传递到管道中的下一个处理程序进行处理。
WebSocket规范中定义了6种类型的桢,netty为其提供了具体的对应的POJO实现。
WebSocketFrame:所有桢的父类,所谓桢就是WebSocket服务在建立的时候,在通道中处理的数据类型。本列子中客户端和服务器之间处理的是文本信息。所以范型参数是TextWebSocketFrame。
WebSocketFrame继承类
自定义Handler
import io.netty.channel.ChannelHandlerC
import io.netty.channel.SimpleChannelInboundH
import io.netty.handler.codec.http.websocketx.TextWebSocketF
import java.time.LocalDateT
//处理文本协议数据,处理TextWebSocketFrame类型的数据,websocket专门处理文本的frame就是TextWebSocketFrame
public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler&TextWebSocketFrame&{
//读到客户端的内容并且向客户端去写内容
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("收到消息:"+msg.text());
* writeAndFlush接收的参数类型是Object类型,但是一般我们都是要传入管道中传输数据的类型,比如我们当前的demo
* 传输的就是TextWebSocketFrame类型的数据
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务时间:"+ LocalDateTime.now()));
//每个channel都有一个唯一的id值
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
//打印出channel唯一值,asLongText方法是channel的id的全名
System.out.println("handlerAdded:"+ctx.channel().id().asLongText());
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerRemoved:" + ctx.channel().id().asLongText());
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("异常发生");
ctx.close();
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&WebSocket客户端&/title&
&script type="text/javascript"&
//如果浏览器支持WebSocket
if(window.WebSocket){
//参数就是与服务器连接的地址
socket = new WebSocket("ws://localhost:8899/ws");
//客户端收到服务器消息的时候就会执行这个回调方法
socket.onmessage = function (event) {
var ta = document.getElementById("responseText");
ta.value = ta.value + "\n"+event.
//连接建立的回调函数
socket.onopen = function(event){
var ta = document.getElementById("responseText");
ta.value = "连接开启";
//连接断掉的回调函数
socket.onclose = function (event) {
var ta = document.getElementById("responseText");
ta.value = ta.value +"\n"+"连接关闭";
alert("浏览器不支持WebSocket!");
//发送数据
function send(message){
if(!window.WebSocket){
//当websocket状态打开
if(socket.readyState == WebSocket.OPEN){
socket.send(message);
alert("连接没有开启");
&form onsubmit="return false"&
&textarea name = "message" style="width: 400height: 200px"&&/textarea&
&input type ="button" value="发送数据" onclick="send(this.form.message.value);"&
&h3&服务器输出:&/h3&
&textarea id ="responseText" style="width: 400height: 300"&&/textarea&
&input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="清空数据"&
启动服务器,然后运行客户端页面,当客户端和服务器端连接建立的时候,服务器端执行handlerAdded回调方法,客户端执行onopen回调方法
服务器端控制台:
handlerAdded:acde48fffe05c11-ce4764fffa940fe-df037eb5
客户端连接建立
客户端发送消息,服务器端进行响应,
浏览器客户端发送消息
服务端控制台打印:
收到消息:websocket程序
客户端也收到服务器端的响应:
浏览器客户端收到服务器端响应
打开开发者工具:
页面发送websocket请求.png
在从标准的HTTP或者HTTPS协议切换到WebSocket时,将会使用一种升级握手的机制。因此,使用WebSocket的应用程序将始终以HTTP/S作为开始,然后再执行升级。这个升级动作发生的确定时刻特定与应用程序;它可能会发生在启动时候,也可能会发生在请求了某个特定的IURL之后。
查看桢信息
在魔都漂泊的有追求的码农,专注后端学习。

我要回帖

更多关于 websocket channel 的文章

 

随机推荐