Веб-сокет перестает отвечать через некоторое время - PullRequest
0 голосов
/ 25 мая 2018

У меня есть служба Windows, которая использует веб-сокет (от http://sta.github.io/websocket-sharp/) для подключения к Slack и отслеживания сообщений.

Мой код подключения выглядит примерно так:

ws = new WebSocket(connection.Url);

ws.OnMessage += async (sender, e) =>
{
    var msg = JsonConvert.DeserializeObject<MessageFromSlack>(e.Data);
    if (msg.Type == "message" && msg.Text != null && msg.User != UserId)
    {
        if (userMatcher.IsMatch(msg.Text))
        {
            await ProcessDirectMessage(msg);
        }
        await ProcessMessage(msg);
    }
    if (msg.Type == "channel_joined")
    {
        await ChannelJoined(msg.ChannelModel.Id);
    }
};

ws.OnClose += (sender, e) =>
{
    var reason = e.Reason;
    var code = e.Code;
    System.Diagnostics.Debug.WriteLine($"{code}:{reason}");
};

ws.Connect();

В основном он ожидает сообщения, а затем, если он направлен @ моему боту, он будет вызывать ProcessDirectMessage, а если нет, то будет вызывать ProcessMessage. Детали этих функций, я думаю, не важны (они делают некоторое соответствиеищите ключевые фразы и отвечайте, отправляя сообщение обратно).

Это все работает нормально. Некоторое время. Но через некоторое время (обычно больше, чем день) он просто перестает отвечать вообще. Мой *Обработчик 1012 * никогда не получает удар. Я подумал, что, возможно, происходит то, что веб-сокет закрывается на стороне сервера, поэтому я добавил обработчик OnClose, но, похоже, он тоже никогда не ударится.

У кого-нибудь есть идея, что здесь может происходить? Есть ли способ сохранить соединение живым или же восстановить его, когда оно умирает?

1 Ответ

0 голосов
/ 25 мая 2018

По характеру TCP-соединения - единственный надежный способ обнаружить его - это что-то записать в него.Если вы просто читаете (ожидаете получения данных) - вы можете делать это в течение очень долгого времени, в то время как другая сторона давно мертва.Это происходит, если эта другая сторона не закрыла соединение изящно (что включает обмен некоторыми TCP-пакетами).

Протокол веб-сокета определяет специальный кадр Ping и соответствующий кадр Pong, который следует использовать, чтобы избежать ситуации, описанной ввопрос.Время от времени вы должны отправлять Ping фрейм и ждать (в течение определенного времени ожидания), пока сервер ответит Pong фреймом.Если он не ответил в течение заданного времени ожидания - предположим, что соединение разорвано, и переподключите.

Насколько я знаю - используемая вами библиотека не отправляет запросы ping от вашего имени автоматически.Тем не менее, это позволяет вам сделать это с помощью метода Ping.

Вам необходимо настроить время ожидания с помощью

ws.WaitTime = TimeSpan.FromSeconds(5);

И затем время от времени (например, когда вы этого не делали).получать любые новые сообщения за последние X секунд), выполните:

bool isAlive = ws.Ping();

Существует также логическое свойство, которое делает то же самое:

bool isAlive = ws.IsAlive;

Это блокирующий вызов (оба из вышеперечисленных).Он вернет true, если сервер ответил с Pong в течение интервала ws.WaitTime, и false в противном случае.Тогда вы можете действовать соответственно.

...