Подключение к websocket с помощью С# (я могу подключиться с помощью JavaScript, но С# дает код состояния 200)

Я новичок в области websocket.

Я могу подключиться к серверу websocket с помощью JavaScript с помощью этого кода:

var webSocket = new WebSocket(url);

Но для моего приложения мне нужно подключиться к тому же серверу с помощью С#. Код, который я использую:

ClientWebSocket webSocket = null;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);

В третьей строке кода возникает следующая ошибка:

"Сервер возвратил код состояния 200, когда ожидался код состояния 101

После небольшого опроса я понял, что каким-то образом сервер не может переключить протокол http на протокол websocket во время процесса подключения.

Я делаю что-то глупое в своем коде С# или что-то не так с сервером. У меня нет доступа к серверу, так как URL-адрес, который я использую, является сторонним.

Не могли бы вы дать мне какое-либо предложение по этому вопросу?

Ответ 1

Используйте библиотеку WebSocketSharp и легко подключайтесь:

Клиент WebSocket

using System;
using WebSocketSharp;

namespace Example
{
  public class Program
  {
    public static void Main (string[] args)
    {
      using (var ws = new WebSocket ("ws://dragonsnest.far/Laputa")) {
        ws.OnMessage += (sender, e) =>
          Console.WriteLine ("Laputa says: " + e.Data);

        ws.Connect ();
        ws.Send ("BALUS");
        Console.ReadKey (true);
      }
    }
  }
}

Шаг 1

Обязательное пространство имен.

using WebSocketSharp;

Класс WebSocket существует в пространстве имен WebSocketSharp.

Шаг 2

Создание нового экземпляра класса WebSocket с URL-адресом WebSocket для подключения.

using (var ws = new WebSocket ("ws://example.com")) {
  ...
}

Класс WebSocket наследует интерфейс System.IDisposable, поэтому вы можете использовать оператор using. И соединение WebSocket будет закрыто с состоянием закрытия 1001 (исчезает), когда элемент управления покидает блок использования.

Шаг 3

Установка событий WebSocket.

Событие WebSocket.OnOpen

Событие WebSocket.OnOpen наступает, когда установлено соединение WebSocket.

ws.OnOpen += (sender, e) => {
  ...
};

Он прошел как System.EventArgs.Empty, поэтому вам не нужно его использовать.

Событие WebSocket.OnMessage

Событие WebSocket.OnMessage наступает, когда WebSocket получает сообщение.

ws.OnMessage += (sender, e) => {
  ...
};

Он прошел как WebSocketSharp.MessageEventArgs.

e.Type property возвращает либо WebSocketSharp.Opcode.Text, либо WebSocketSharp.Opcode.Binary, который представляет тип сообщения. Таким образом, проверив его, вы можете определить, какой элемент вы должны использовать.

Если он возвращает Opcode.Text, вы должны использовать свойство e.Data, которое возвращает строку (представляет текстовое сообщение).

Или, если он возвращает Opcode.Binary, вы должны использовать свойство e.RawData, которое возвращает байт [] (представляет двоичное сообщение).

if (e.Type == Opcode.Text) {
  // Do something with e.Data.
  ...

  return;
}

if (e.Type == Opcode.Binary) {
  // Do something with e.RawData.
  ...

  return;
}

Событие WebSocket.OnError

Событие WebSocket.OnError наступает, когда WebSocket получает ошибку.

ws.OnError += (sender, e) => {
  ...
};

Он прошел как WebSocketSharp.ErrorEventArgs.

Свойство e.Message возвращает строку, которая представляет сообщение об ошибке.

Если ошибка вызвана исключением, свойство e.Exception возвращает экземпляр System.Exception, вызвавший ошибку.

Событие WebSocket.OnClose

Событие WebSocket.OnClose наступает, когда соединение WebSocket было закрыто.

ws.OnClose += (sender, e) => {
  ...
};

Он прошел как WebSocketSharp.CloseEventArgs.

Свойство e.Code возвращает ushort, представляющий код состояния, указывающий причину закрытия, а свойство e.Reason возвращает строку, представляющую причину закрытия.

Шаг 4

Подключение к серверу WebSocket.

ws.Connect ();

Если вы хотите подключиться к серверу асинхронно, вы должны использовать метод WebSocket.ConnectAsync().

Шаг 5

Отправка данных на сервер WebSocket.

ws.Send (data);

Метод WebSocket.Send перегружен.

Вы можете использовать метод WebSocket.Send(string), WebSocket.Send(byte[]) или WebSocket.Send(System.IO.FileInfo) для отправки данных.

Если вы хотите отправить данные асинхронно, вы должны использовать метод WebSocket.SendAsync.

ws.SendAsync (data, completed);

А также, если вы хотите что-то сделать, когда отправка завершена, вы должны установить в качестве завершенного любой делегат Action<bool>.

Шаг 6

Закрытие соединения WebSocket.

ws.Close (code, reason);

Если вы хотите явно закрыть соединение, вам следует использовать метод WebSocket.Close.

Метод WebSocket.Close перегружен.

Вы можете использовать метод WebSocket.Close(), WebSocket.Close(ushort), WebSocket.Close(WebSocketSharp.CloseStatusCode), WebSocket.Close(ushort, string) или WebSocket.Close(WebSocketSharp.CloseStatusCode, метод close). подключение.

Если вы хотите закрыть соединение асинхронно, вы должны использовать метод WebSocket.CloseAsync.

Ответ 2

Если вы подключаетесь к клиенту WebSocket и получаете HTTP 200 как ответ, значит, вы, вероятно, подключаетесь к неправильному месту (хост, путь и/или порт).

В принципе, вы подключаетесь к нормальной конечной точке HTTP, которая не понимает ваше требование к WebSocket, и она просто возвращает ответ "ОК" (HTTP 200). Вероятно, сервер WebSocket работает на другом порту или пути на том же сервере.

Проверьте свой URL.

Ответ 3

Не совсем уверен, что случилось с пакетом nuget WebSocketSharp, однако я заметил, что теперь WebSocket # отображается как наиболее релевантный результат в репозитории nuget. Мне потребовалось некоторое время, прежде чем я понял, что 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);
        }
    }
}

Ответ 4

URL-адреса веб-сокета должны начинаться с ws:// или wss:// где последний является защищенным веб-сокетом.

Ответ 5

Поскольку WebsocketSharp не совместим с .NET Core, я предлагаю использовать эту библиотеку. Вот пример кода

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. В противном случае это не работает.