Немедленно обнаружьте клиентское разъединение от сокета сервера

Ваш ajax-вызов не имеет никакого отношения к ссылке тега привязки. Итак, у вас есть какой-нибудь метод в домашнем контроллере, который возвращает данные для просмотра в виде viewresult .?

Можете ли вы вставить свой полный код контроллера

71
задан cHao 8 May 2012 в 13:28
поделиться

7 ответов

С тех пор нет никаких событий, доступных для передачи сигналов, когда сокет разъединяется, необходимо будет опросить его на частоте, которая приемлема для Вас.

Используя этот дополнительный метод, у Вас может быть надежный метод, чтобы обнаружить, если сокет разъединяется.

static class SocketExtensions
{
  public static bool IsConnected(this Socket socket)
  {
    try
    {
      return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
    }
    catch (SocketException) { return false; }
  }
}
101
ответ дан Samuel 24 November 2019 в 13:00
поделиться

Можно также проверить.IsConnected свойство сокета, если необходимо было опросить.

-1
ответ дан theG 24 November 2019 в 13:00
поделиться

Реализация heartbeat в Вашу систему могла бы быть решением. Это только возможно, если оба клиента и сервера находятся под Вашим контролем. Вы можете сделать, чтобы DateTime возразил отслеживанию времени, когда последние байты были получены от сокета. И предположите, что сокет не ответил по определенному интервалу, потеряны. Это будет только работать, если у Вас будет heartbeat / пользовательский поддерживают реализованный.

3
ответ дан Niran 24 November 2019 в 13:00
поделиться

Это просто не возможно. Нет никакого физического соединения между Вами и сервером (кроме чрезвычайно редкого случая, где Вы соединяетесь между двумя compuers с петлевым кабелем).

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

Поэтому "немедленно" нереалистично. Лучшее, которое можно сделать, в течение периода тайм-аута, который зависит от платформы, на которой работает код.

Править: Если Вы только ищете корректные соединения, то, почему не только отправляют команду "DISCONNECT" на сервер от Вашего клиента?

13
ответ дан Erik Funkenbusch 24 November 2019 в 13:00
поделиться

Разве нельзя просто использовать Select?

Используйте select на подключенной розетке. Если select возвращается с вашим сокетом как Ready, но последующий Receive возвращает 0 байтов, это означает, что клиент отключил соединение. AFAIK, это самый быстрый способ определить, отключился ли клиент.

Я не знаю C #, поэтому просто игнорируйте, если мое решение не подходит для C # (хотя C # предоставляет select ) или если я неправильно поняли контекст.

0
ответ дан 24 November 2019 в 13:00
поделиться

«TCP работает именно так, и вам придется с этим мириться»

Ага, вы правы. Я пришел к выводу, что это факт жизни. Вы увидите такое же поведение даже в профессиональных приложениях, использующих этот протокол (и даже другие). Я даже видел это в онлайн-играх; ваш приятель говорит «до свидания», и он, кажется, находится в сети еще 1-2 минуты, пока сервер не «очистит дом».

Вы можете использовать предложенные здесь методы или реализовать «сердцебиение», как также предлагается . Я выбираю первое. Но если бы я выбрал последнее, я бы просто попросил сервер «пинговать» каждого клиента время от времени одним байтом и посмотреть, есть ли у нас тайм-аут или нет ответа. Вы даже можете использовать фоновый поток, чтобы добиться этого с точным временем. Возможно, даже комбинация может быть реализована в каком-то списке опций (флаги перечисления или что-то в этом роде), если вы действительно беспокоитесь об этом. Но небольшая задержка с обновлением сервера не такая уж большая проблема, если вы ДЕЙСТВИТЕЛЬНО обновляете. Это Интернет, и никто не ждет от него волшебства! :)

6
ответ дан 24 November 2019 в 13:00
поделиться
[

] я нашел весьма полезное, еще одно обходное решение![

] [

]Если вы используете асинхронные методы для чтения данных из сетевого сокета (я имею в виду использование []BeginReceive[] - []EndReceive[]), то всякий раз, когда соединение прерывается, появляется одна из таких ситуаций: Либо отправляется сообщение без данных (это можно увидеть с помощью []Socket.Available[] - даже при срабатывании []BeginReceive[], его значение будет равно нулю), либо значение []Socket.Connected[] становится ложным в этом вызове (не пытайтесь тогда использовать []EndReceive[]). [

] [

]Я выкладываю использованную мной функцию, думаю, что из этого лучше видно, что я имел в виду:[

] [
] [
private void OnRecieve(IAsyncResult parameter) 
{
    Socket sock = (Socket)parameter.AsyncState;
    if(!sock.Connected || sock.Available == 0)
    {
        // Connection is terminated, either by force or willingly
        return;
    }

    sock.EndReceive(parameter);
    sock.BeginReceive(..., ... , ... , ..., new AsyncCallback(OnRecieve), sock);

    // To handle further commands sent by client.
    // "..." zones might change in your code.
}
]
2
ответ дан 24 November 2019 в 13:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: