当前位置: 首页 > news >正文

广东建设行业招聘 什么网站网页平台做个业务推广

广东建设行业招聘 什么网站,网页平台做个业务推广,长沙网站seo源头厂家,什么是网络营销的tgi值.NET斗鱼直播弹幕客户端(2021)离之前更新的两篇《.NET斗鱼直播弹幕客户端》已经有一段时间#xff0c;近期有许多客户向我反馈刚好有这方面的需求#xff0c;但之前的代码不能用了——但网上许多流传的Node.js、Python脚本却可以用#xff0c;这岂能忍#xff1f;#xff… .NET斗鱼直播弹幕客户端(2021)离之前更新的两篇《.NET斗鱼直播弹幕客户端》已经有一段时间近期有许多客户向我反馈刚好有这方面的需求但之前的代码不能用了——但网上许多流传的Node.js、Python脚本却可以用这岂能忍刚好我终于找回了我的发布密码????因此我有动力重新对此进行好(xie)好(xie)研(bo)究(ke)。为何之前的不能用了重新运行之前的C#脚本发现是在这一行报错的using var client  new TcpClient(); await client.ConnectAsync(openbarrage.douyutv.com, 8601); // 这里报错 网上查了查发现斗鱼确实已经停止使用openbarrage.douyutv.com:8601了。进一步查资料显示新url改成了danmuproxy.douyu.com斗鱼已经统一使用WebSocket协议之前为TCP协议经过进一步对比新协议代码示例发现协议过程没有任何区别序列化也依然用的STT算法。私货时间 我认为斗鱼这样做合理因为WebSocket性能不差且不需再为浏览器和第三方接口各自维护两套不同的代码。 具体过程如下建立WebSocket连接发送登录请求可匿名加入指定的房间号每隔45秒响应一次心跳包此时即可正常接收弹幕数据新代码实现.NET中有许多提供WebSocket功能的库和第三方包之前我经常用websocket-sharp这是第三方包。现在我们尽量不用第三方包官方提供的WebSocket客户端叫System.Net.WebSockets.ClientWebSocket同时支持.NET 4.5和.NET Core。按正常的思路我们会这样写return Observable.Createstring(async (roomId, cancellationToken)  {using var ws  new ClientWebSocket();await ws.ConnectAsync(new Uri(wss://danmuproxy.douyu.com:8506/), cancellationToken);await MsgTool.LoginAsync(ws, roomId, cancellationToken);// other codes }); 但实际运行却不行会报这个错WebSocketException: The Sec-WebSocket-Accept header value Kfh9QIsMVZcl6xEPYxPHzW8SZ8w is invalid. 相信我如果你仔细对比Node/Python和.NET代码整个代码中没任何区别但打开Fiddler仔细分析协议发现事情没这么简单这是一个无法成功连上服务器的包请求 GET https://danmuproxy.douyu.com:8506/ HTTP/1.1 Host: danmuproxy.douyu.com:8506 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Version: 13 Sec-WebSocket-Key: VsPg1/SSskKrbYouGm3ROQ响应 HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: Kfh9QIsMVZcl6xEPYxPHzW8SZ8w Sec-WebSocket-Version: 13 EndTime: 09:37:44.958 ReceivedBytes: 0 SentBytes: 0 研究原因其中请注意看请求中的Sec-WebSocket-Key项和响应中的Sec-WebSocket-Accept项。按照WebSocket协议(https://tools.ietf.org/html/rfc6455#p-11.3.3)服务器响应头Sec-WebSocket-Accept项的值应该为请求头Sec-WebSocket-Key项字符串追加固定值258EAFA5-E914-47DA-95CA-C5AB0DC85B11然后计算其SHA1哈希值再求Base64用C#代码说这一过程如下string WebSocketComputeAccept(string key) {using var sha  SHA1.Create();byte[] hash  sha.ComputeHash(Encoding.UTF8.GetBytes(key  258EAFA5-E914-47DA-95CA-C5AB0DC85B11));return Convert.ToBase64String(hash); } 如上的VsPg1/SSskKrbYouGm3ROQ按这个计算过程它应该返回VrPdUdxpPeBXDi1ttGN607h8ct0但实际却是Kfh9QIsMVZcl6xEPYxPHzW8SZ8w这就是为何C#会报错因此服务端返回了错误值。进一步研究原因我尝试了许多次C#用客户端连接时总是会生成随机的Sec-WebSocket-Key值但不管值如何服务端总是会返回相同的值——但一旦切换为Node.js返回的值就完全正常。我仔细分析了其它语言的WebSocket头与.NET的区别发现一个重要因素.NET客户端请求中的Sec-WebSocket-Key项一定是最后一条但其它语言中不是最后一条。如果我们使用Fiddler手动发送握手请求将Sec-WebSocket-Key与Sec-WebSocket-Version顺序对调一下发现响应值如下服务器响应匹配HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: VrPdUdxpPeBXDi1ttGN607h8ct0 Sec-WebSocket-Version: 13 然而用ClientWebSocket是无法控制请求头顺序的这一点可以在源代码中找到。最终答案虽然无法控制请求头顺序但可以控制Sec-WebSocket-Key不是最后一个只需添加一个子协议头值无所谓ws.Options.AddSubProtocol(-);因此重点代码如下完整代码请见LINQPad脚本——douyu-2020.linqusing var ws  new ClientWebSocket(); ws.Options.AddSubProtocol(-); await ws.ConnectAsync(new Uri(wss://danmuproxy.douyu.com:8506), QueryCancelToken); await ws.SendAsync(SerializeDouyu($typeloginreq/roomid74751/ver20190610/), WebSocketMessageType.Binary, false, QueryCancelToken); await ws.SendAsync(SerializeDouyu($typejoingroup/rid74751/gid-9999/), WebSocketMessageType.Binary, false, QueryCancelToken); _  Task.Run(async ()  {while (!QueryCancelToken.IsCancellationRequested){await Task.Delay(45000, QueryCancelToken);await ws.SendAsync(SerializeDouyu($typemrkl/), WebSocketMessageType.Binary, false, QueryCancelToken);} });while (!QueryCancelToken.IsCancellationRequested) {var buffer  new byte[4096];WebSocketReceiveResult r  await ws.ReceiveAsync(buffer, QueryCancelToken);string result  DeserializeDouyu(new Memorybyte(buffer, 0, r.Count), QueryCancelToken);DecodeStringToJObject(result).Dump(); } 运行效果封装优化之前我是基于System.Reactive库做的封装但C# 9.0已经发布许久这次我重新基于IAsyncEnumerable写了一版这个以C# 9.0作为异步流的基础扩展可以用System.Linq.Async从而获得与正常的LINQ完全一致的体验核心代码如下public class DouyuBarrage {static HttpClient http  new HttpClient();public static async IAsyncEnumerablestring RawFromUrl(string url, [EnumeratorCancellation] CancellationToken cancellationToken  default){HttpResponseMessage html  await http.GetAsync(url, cancellationToken);var roomId  Regex.Match(await html.Content.ReadAsStringAsync(), \$ROOM.room_id[ ]?[ ]?(\d);).Groups[1].Value;using var ws  new ClientWebSocket();ws.Options.AddSubProtocol(-);await ws.ConnectAsync(new Uri(wss://danmuproxy.douyu.com:8506/), cancellationToken);await MsgTool.LoginAsync(ws, roomId, cancellationToken);await MsgTool.JoinGroupAsync(ws, roomId, cancellationToken);var task  Task.Run(async () {while (!cancellationToken.IsCancellationRequested){await MsgTool.SendTick(ws, cancellationToken);await Task.Delay(45000, cancellationToken);}}, cancellationToken);while (ws.State  WebSocketState.Open  !cancellationToken.IsCancellationRequested){yield return await MsgTool.RecieveAsync(ws, cancellationToken);}GC.KeepAlive(task);await MsgTool.Logout(ws, cancellationToken);}public static IAsyncEnumerableJToken JObjectFromUrl(string url)  RawFromUrl(url).Select(MsgTool.DecodeStringToJObject);public static IAsyncEnumerableBarrage ChatMessageFromUrl(string url)  JObjectFromUrl(url).Where(x  x[type].Valuestring()  chatmsg).Select(Barrage.FromJToken); } 见最后两个方法JObjectFromUrl、ChatMessageFromUrl基于IAsyncEnumerable可以获得与LINQ、System.Reactive完全一致的开发体验一行代码即可完成异步流的筛选、数据转换。说在最后以上所有的完整代码和示例都已经上传到我的博客专用Github仓库各位可以自行前往下载https://github.com/sdcb/blog-data/tree/master/2021/20191011-douyu-barrage-with-dotnet喜欢的朋友 请关注我的微信公众号【DotNet骚操作】DotNet骚操作
http://www.zqtcl.cn/news/167147/

相关文章:

  • 网站建设免费国外撤销网站备案申请书
  • 佛山做网站那家好网站建设公司如何盈利
  • 傻瓜建网站设计感网站
  • 北京网站优化软件陕西省建筑信息平台
  • 广州越秀建网站济南房产网新开楼盘
  • 线上咨询预约网站建设方案保定外贸网站制作
  • 网站流量如何增加提高工作效率的措施
  • 龙湖镇华南城网站建设.net 网站开发书籍
  • 域名费用和网站服务器费用是同样的吗推广营销方案
  • 安徽网站设计方案中文外贸网站有哪些
  • 衡阳手机网站设计响应式网站做多大的尺寸
  • 海尔电子商务网站建设预算灵台县门户网
  • 四川网站建设设计公司排名开发公司与建筑公司合作协议
  • 江西智能网站建设嘉定注册公司
  • 海口网站建设联系方式十大免费软文推广平台
  • 石碣镇做网站帮别人做网站开价
  • 站长 网站ip客户都不愿意做网站
  • 网站开发和软件开发哪个难网站备案账号
  • 2昌平区网站建设安徽盛绿建设网站
  • 商务网站建设目的天津建设网站需要的费用
  • flash 网站头部wordpress支持大文件上传
  • 网站开发方式的选择凡客设计
  • 常德建设网站如何查询某个网站的设计公司
  • wordpress 仿站教程学校ui设计培训
  • 南昌模板建站定制网站合肥瑶海区网站建设价格
  • 奥尔马手表官方网站导出wordpress文章
  • 网站栏目内容和功能手机网站建设 如何获得更好的排名
  • 网站运营推广难做常德网警
  • 北滘网站建设公司在百度上做网站怎么做
  • 合肥网站建设 毅耘园林设计网站大全