我是新的领域的WebSocket。
我可以使用JavaScript连接到WebSocket服务器,使用以下代码:
var webSocket = new WebSocket(url);
但是对于我的应用程序,我需要使用C#连接到同一个服务器,我正在使用的代码是:
ClientWebSocket webSocket = null;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
代码的第3行导致以下错误:
“服务器返回状态代码200,而预期状态代码101”
经过一点调查,我意识到不知何故,服务器不能切换http协议到WebSocket协议在连接过程中。
我在我的C#代码中做了什么愚蠢的事情或者服务器出了问题。我没有任何访问服务器的权限,因为我使用的URL是第三方的。
关于这个问题,你能给我提些建议吗?
6条答案
按热度按时间iyr7buue1#
靶病变; DR:
在循环中使用
ReceiveAsync()
,直到收到Close
帧或取消CancellationToken
。这就是您获取消息的方式。发送是直接的,只需SendAsync()
。不要在CloseOutputAsync()
之前使用CloseAsync()
-因为您希望先停止接收循环。否则-CloseAsync()
将挂起,或者使用CancellationToken
退出ReceiveAsync()
-CloseAsync()
将抛出。我从https://mcguirev10.com/2019/08/17/how-to-close-websocket-correctly.html中学到了很多。
完整答案:
你只需要在一个循环中执行
ReceiveAsync()
,当你收到一个特殊的Close
帧时结束,所以当你想断开连接时,你必须告诉服务器你用CloseOutputAsync
关闭,这样它就会回复一个类似的Close
帧给你的客户端,这样它就可以结束接收。我的代码示例只说明了最基本的外部传输机制。因此,您发送和接收原始的二进制消息。此时,您无法分辨特定的服务器响应是否与您发送的特定请求相关。您必须在对消息进行编码/解码后自己匹配它们。可以使用任何序列化工具来实现这一点,但许多加密货币市场使用Google的Protocol Buffers。名称说明了一切;)
匹配任何唯一的随机数据都可以使用。你需要令牌,在C#中我使用
Guid
类。然后我使用请求/响应匹配来使请求工作而不依赖于事件。
SendRequest()
方法等待直到匹配的响应到达,或者...连接被关闭。非常方便,并且允许比基于事件的方法更可读的代码。当然,你仍然可以在接收到的消息上调用事件,只要确保它们不与任何需要响应的请求匹配。哦,在我的
async
方法中,我使用了SemaphoreSlim
。每个请求都将其自己的信号量放入一个特殊的字典中,当我得到响应时,我通过响应令牌找到条目,释放信号量,处理它,从字典中删除。看起来很复杂,但实际上非常简单。顺便说一句,为什么要使用其他的库而不是. NET内置的呢?我找不到任何原因,除了微软的类的文档可能很差。也许-如果出于一些真正奇怪的原因,你想使用现代的WebSocket传输与古老的. NET框架;)
哦,我还没有测试过这个例子。它取自测试过的代码,但是所有内部协议部分都被删除了,只留下了传输部分。
rlcwz9us2#
由于WebsocketSharp不兼容. NETCore,我建议使用websocket-client。
请务必使用
ManualResetEvent
。否则它将不起作用。bogh5gae3#
如果您使用WebSocket客户端连接,并收到HTTP 200作为响应,则意味着您可能连接到了错误的位置(主机、路径和/或端口)。
基本上,您连接到的是一个普通的HTTP端点,它不理解您的WebSocket需求,并且它只是返回“OK”响应(HTTP 200)。可能WebSocket服务器运行在同一服务器的另一个端口或路径中。
检查您的URL。
raogr8fs4#
不太清楚WebSocketSharp nuget包发生了什么,但是我注意到现在WebSocket#在nuget repo中显示为最相关的结果。我花了一些时间才意识到
Connect()
现在返回Task
,希望这个例子对某人有用:8cdiaqws5#
上面提到的所有库都是Wrappers,执行此操作的. NetFrameworks类是System.Net.WebSockets.ClientWebSocket
sy5wg1nm6#
WebSocket URL应以
ws://
或wss://
开头,后者是安全Websocket。