使用C#连接到websocket(我可以使用JavaScript连接,但C#给出状态代码200错误)
我是websocket领域的新手 我可以使用以下代码使用JavaScript连接到websocket服务器:使用C#连接到websocket(我可以使用JavaScript连接,但C#给出状态代码200错误),javascript,c#,websocket,Javascript,C#,Websocket,我是websocket领域的新手 我可以使用以下代码使用JavaScript连接到websocket服务器: var webSocket = new WebSocket(url); 但是对于我的应用程序,我需要使用c#连接到同一台服务器。我使用的代码是: ClientWebSocket webSocket = null; webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri(url), Cancellat
var webSocket = new WebSocket(url);
但是对于我的应用程序,我需要使用c#连接到同一台服务器。我使用的代码是:
ClientWebSocket webSocket = null;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
代码的第三行导致以下错误:
“当状态代码为101时,服务器返回了状态代码200”
经过一点调查,我意识到服务器在连接过程中无法将http协议切换到websocket协议
我的C#代码有什么愚蠢的地方吗?或者服务器出了问题。我没有任何访问服务器的权限,因为我使用的url是第三方的
关于这个问题,您能给我一些建议吗?如果您连接到WebSocket客户端,并得到HTTP 200作为响应,则表示您可能连接到了错误的位置(主机、路径和/或端口) 基本上,您正在连接到一个不理解WebSocket需求的普通HTTP端点,它只是返回“OK”响应(HTTP 200)。WebSocket服务器可能在同一服务器的另一个端口或路径中运行
检查您的URL。Websocket URL应该以
ws://
或wss://
开头,后者是安全的Websocket。不太确定WebSocketSharp nuget包发生了什么,但是我注意到现在是nuget repo中最相关的结果。我花了一些时间才意识到,Connect()
现在正在返回Task
,希望这个示例对某人有用:
using System;
using System.Threading.Tasks;
using WebSocketSharp;
namespace Example
{
class Program
{
private static void Main(string[] args)
{
using (var ws = new WebSocket(url: "ws://localhost:1337", onMessage: OnMessage, onError: OnError))
{
ws.Connect().Wait();
ws.Send("Hey, Server!").Wait();
Console.ReadKey(true);
}
}
private static Task OnError(ErrorEventArgs errorEventArgs)
{
Console.Write("Error: {0}, Exception: {1}", errorEventArgs.Message, errorEventArgs.Exception);
return Task.FromResult(0);
}
private static Task OnMessage(MessageEventArgs messageEventArgs)
{
Console.Write("Message received: {0}", messageEventArgs.Text.ReadToEnd());
return Task.FromResult(0);
}
}
}
由于WebsocketSharp与.NET内核不兼容,我建议使用。 下面是一些示例代码
static async Task Main(string[] args)
{
var url = new Uri("wss://echo.websocket.org");
var exitEvent = new ManualResetEvent(false);
using (var client = new WebsocketClient(url))
{
client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message: {msg}"));
await client.Start();
await client.Send("Echo");
exitEvent.WaitOne();
}
Console.ReadLine();
}
确保使用
ManualResetEvent
。否则它就不能工作。上面提到的所有库都是包装器。执行此操作的.Net Framework类是TL;博士:
在循环中使用ReceiveAsync()
,直到收到Close
帧或取消CancellationToken
为止。这就是你收到信息的方式。发送是直接的,只需sendsync()
。不要在CloseOutputAsync()
之前使用CloseAsync()
——因为您想先停止接收循环。否则-要么CloseAsync()
将挂起,要么如果使用CancellationToken
退出ReceiveAsync()
,CloseAsync()
将抛出
我从中学到了很多
完整答案:
使用Dotnet客户端,这里有一个从我的实际代码中剪下的示例,演示如何进行握手。最重要的一点是,大多数人都不了解这个东西是如何运作的,那就是当收到一条消息时,没有什么神奇的事情发生。你自己创造它。怎么做
您只需在一个循环中执行ReceiveAsync()
,该循环在接收到特殊的Close
帧时结束。因此,当您想要断开连接时,您必须告诉服务器您用CloseOutputAsync
关闭,这样它将用类似的Cloce
帧回复您的客户端,这样它就可以结束接收
我的代码示例仅说明了最基本的外部传输机制。因此,您可以发送和接收原始二进制消息。此时,您无法判断特定服务器响应是否与您发送的特定请求相关。在编码/解码消息后,您必须自己匹配它们。使用任何序列化工具,但许多加密货币市场使用谷歌的协议缓冲区。名字说明了一切;)
对于匹配,可以使用任何唯一的随机数据。您需要令牌,在C#中,我使用Guid
class来实现这一点
然后,我使用请求/响应匹配使请求在不依赖于事件的情况下工作。SendRequest()
方法等待匹配的响应,或者。。。连接已关闭。非常方便,可以让代码比基于事件的方法更具可读性。当然,您仍然可以对收到的消息调用事件,只需确保它们与任何需要响应的请求都不匹配
哦,对于我的async
方法中的等待,我使用SemaphoreSlim
。每个请求都将自己的信号量放在一个特殊的字典中,当我得到响应时,我通过响应令牌找到条目,释放信号量,处理它,从字典中删除。看起来很复杂,但实际上很简单
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用System.Net.WebSockets;
使用系统线程;
使用System.Threading.Tasks;
名称空间示例{
公共类WsClient:IDisposable{
public int ReceiveBufferSize{get;set;}=8192;
公共异步任务ConnectAsync(字符串url){
如果(WS!=null){
if(WS.State==WebSocketState.Open)返回;
else-WS.Dispose();
}
WS=新客户端WebSocket();
如果(CTS!=null)CTS.Dispose();
CTS=新的CancellationTokenSource();
等待WS.ConnectAsync(新的Uri(url)、CTS.Token);
wait Task.Factory.StartNew(ReceiveLoop、CTS.Token、TaskCreationOptions.longlunning、TaskScheduler.Default);
}
公共异步任务DisconnectAsync(){
如果(WS为null)返回;
//TODO:请求清理代码,依赖于子协议。
if(WS.State==WebSocketState.Open){
CTS.CancelAfter(TimeSpan.FromSeconds(2));
等待WS.CloseOutputAsync(WebSocketCloseStatus.Empty,”,CancellationToken.None);
等待WS.CloseAsync(WebSocketCloseStatus.NormalClose,“,CancellationToken.None);
}
WS.Dispose();
WS=null;
CTS.Dispose();
CTS=null;
}
专用异步任务ReceiveLoop(){