boost :: asio socket не обнаруживает перезагрузку удаленного сервера [duplicate]

Это очень распространенная проблема, с которой мы сталкиваемся, борясь с «таинствами» JavaScript.

Давайте начнем с простой функции JavaScript:

function foo(){
// do something 
 return 'wohoo';
}

let bar = foo(); // bar is 'wohoo' here

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

Теперь добавим немного завихрения, введя небольшую задержку в нашей функции, чтобы все строки кода не выполнялись последовательно. Таким образом, он будет эмулировать асинхронное поведение функции:

function foo(){
 setTimeout( ()=>{
   return 'wohoo';
  }, 1000 )
}

let bar = foo() // bar is undefined here

Итак, вы идете, эта задержка просто сломала функциональность, которую мы ожидали! Но что именно произошло? Ну, на самом деле это довольно логично, если вы посмотрите на код. функция foo() после выполнения ничего не возвращает (таким образом, возвращаемое значение равно undefined), но оно запускает таймер, который выполняет функцию после 1s, чтобы вернуть «wohoo». Но, как вы можете видеть, значение, присвоенное бару, является немедленно возвращенным материалом из foo (), а не что-либо еще, что приходит позже.

Итак, как мы решаем эту проблему?

Давайте попросим нашу функцию для ОБЕЩАНИЯ. Обещание действительно о том, что это означает: это означает, что функция гарантирует, что вы предоставите любой результат, который он получит в будущем. поэтому давайте посмотрим на это в нашей маленькой проблеме выше:

function foo(){
   return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
    setTimeout ( function(){ 
      // promise is RESOLVED , when exececution reaches this line of code
       resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
    }, 1000 )
  })
}

let bar ; 
foo().then( res => {
 bar = res;
 console.log(bar) // will print 'wohoo'
});

Таким образом, резюме - для решения асинхронных функций, таких как вызовы на основе ajax и т. д., вы можете использовать обещание resolve значение (которое вы намерены вернуть). Таким образом, короче говоря, вы разрешаете значение вместо возврата в асинхронных функциях.

63
задан Zxaos 28 July 2014 в 20:23
поделиться

12 ответов

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

Это отличная дискуссия по различным методам проверки того, что клиент отключился: Стивен Клири, обнаружение полуоткрытых (отброшенных) соединений .

* для Windows использовать ioctlsocket.

4
ответ дан Troyseph 26 August 2018 в 20:38
поделиться

Возвращаемое значение приема будет равным -1, если соединение потеряно иначе, это будет размер буфера.

void ReceiveStream(void *threadid)
{
    while(true)
    {
        while(ch==0)
        {
            char buffer[1024];
            int newData;
            newData = recv(thisSocket, buffer, sizeof(buffer), 0);
            if(newData>=0)
            {
                std::cout << buffer << std::endl;
            }
            else
            {
                std::cout << "Client disconnected" << std::endl;
                if (thisSocket)
                {
                    #ifdef WIN32
                        closesocket(thisSocket);
                        WSACleanup();
                    #endif
                    #ifdef LINUX
                        close(thisSocket);
                    #endif
                }
                break;
            }
        }
        ch = 1;
        StartSocket();
    }
}
0
ответ дан Anand Paul 26 August 2018 в 20:38
поделиться

Попробуйте найти EPOLLHUP или EPOLLERR. Как проверить соединение с клиентом все еще жив

Чтение и поиск 0 будут работать в некоторых случаях, но не во всех.

0
ответ дан Community 26 August 2018 в 20:38
поделиться

Я играл с несколькими решениями, но этот, похоже, лучше всего подходит для обнаружения отключения хоста и / или клиента в Windows. Он предназначен для неблокирующих сокетов и получен из примера IBM .

char buf;
int length=recv(socket, &buf, 0, 0);
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0){
    return 0;
}   
if (nError==0){
    if (length==0) return 0;
}
-2
ответ дан Galleon 26 August 2018 в 20:38
поделиться

Если вы используете перекрывающиеся (то есть асинхронные) операции ввода-вывода с процедурами завершения или порты завершения, вы будете немедленно уведомлены (при условии, что у вас есть прочитанное сообщение), когда клиентская сторона закрывает соединение.

2
ответ дан Graeme Perrow 26 August 2018 в 20:38
поделиться

Этот вопрос основан на различных заблуждениях относительно сетевого стека.

Прежде всего, нет понятия «соединение» Tcp или иначе, и чем раньше вы сделаете это различие, тем скорее вы поймете, что это ничем не отличается от udp или любого другого протокола.

Когда вы получаете время, у вас либо есть данные для отправки, либо нет.

Если вы не хотите передавать, чем, необязательно увеличивайте время ожидания и получаете снова.

Если клиент отключил компьютер или иным образом отключился, то как и почему это имеет значение?

Разве это сломает ваше «соединение»? Может быть, но, возможно, нет, кто знает, как настроен ваш компьютер или LSP.

Обычный способ сделать это аналогичен любым другим протоколам, и я напоминаю вам, что сокет уже «подключен», в случаях, когда происходит регенерация.

Когда вы пытаетесь отправить этому клиенту что-то, что вы узнаете, если клиент «подключен» или более правильно подтвердил ваши данные под Tcp. (В udp также зависит от сети через icmp)

Почему вы проголосовали за этот ответ из-за своего собственного недоразумения.

Короче говоря, если у вас есть данные для отправки отправки и определения того, какое действие требуется после отправки или неудачи.

Если время срабатывания вашей приемки одинаково, и, при желании, вы можете использовать отправку размера 0, чтобы подтвердить, что другая сторона все еще принимает ваши данные.

-7
ответ дан Jay 26 August 2018 в 20:38
поделиться

TCP имеет «открытые» и «закрытые» процедуры в протоколе. После «открытия» соединение удерживается до «закрытого». Но есть много вещей, которые могут остановить поток данных ненормально. При этом методы определения того, можно ли использовать ссылку, сильно зависят от уровней программного обеспечения между протоколом и прикладной программой. Те, о которых упоминалось выше, сосредоточены на программиста, пытающегося использовать сокет неинвазивным способом (чтение или запись 0 байтов), возможно, являются наиболее распространенными. Некоторые слои в библиотеках будут предоставлять «опрос» для программиста. Например, вызовы Win32 asych (delayed) могут начать чтение, которое будет возвращаться без ошибок и 0 байтов, чтобы сигнализировать сокет, который больше не может быть прочитан (предположительно, процедура TCP FIN). В других средах могут использоваться «события», как определено в их обертывающих слоях. На этот вопрос нет единого ответа. Механизм обнаружения, когда сокет не может использоваться и должен быть закрыт, зависит от оберток, поставляемых в библиотеках. Также стоит отметить, что сами сокеты могут быть повторно использованы слоями под библиотекой приложений, поэтому разумно разобраться, как ваша среда работает с интерфейсом Berkley Sockets.

0
ответ дан jlpayton 26 August 2018 в 20:38
поделиться

Чтобы увеличить это немного:

Если вы используете сервер, вам нужно либо использовать TCP_KEEPALIVE для мониторинга клиентских подключений, либо сделать что-то подобное себе, либо иметь знания о данных / протоколе что вы работаете над соединением.

В принципе, если соединение будет убито (т. е. неправильно закрыто), то сервер не заметит, пока он не попытается что-то написать клиенту, что является то, что keepalive для вас. В качестве альтернативы, если вы знаете протокол лучше, вы можете просто отключиться от таймаута бездействия.

11
ответ дан Peter Jeffery 26 August 2018 в 20:38
поделиться

Мы столкнулись с подобной проблемой, когда обнаружение удаления кабеля на ПК было проблемой. После googling мы попали в SuperCom для библиотеки TCP, которая предложила эту функцию и очень надежную библиотеку передачи данных, которая также могла обрабатывать события отчетности, когда соединение было закрыто.

-3
ответ дан pgmonthego 26 August 2018 в 20:38
поделиться

apr-библиотека из проекта apache является хорошей ссылкой для этой проблемы. Он использует опрос с тайм-аутом, чтобы проверить, нарушено ли соединение другой стороны.

-2
ответ дан Sam Liao 26 August 2018 в 20:38
поделиться
"""
tcp_disconnect.py
Echo network data test program in python. This easily translates to C & Java.

A server program might want to confirm that a tcp client is still connected 
before it sends a data. That is, detect if its connected without reading from socket.
This will demonstrate how to detect a TCP client disconnect without reading data.

The method to do this:
1) select on socket as poll (no wait)
2) if no recv data waiting, then client still connected
3) if recv data waiting, the read one char using PEEK flag 
4) if PEEK data len=0, then client has disconnected, otherwise its connected.
Note, the peek flag will read data without removing it from tcp queue.

To see it in action: 0) run this program on one computer 1) from another computer, 
connect via telnet port 12345, 2) type a line of data 3) wait to see it echo, 
4) type another line, 5) disconnect quickly, 6) watch the program will detect the 
disconnect and exit.

John Masinter, 17-Dec-2008
"""

import socket
import time
import select

HOST = ''       # all local interfaces
PORT = 12345    # port to listen

# listen for new TCP connections
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
# accept new conneciton
conn, addr = s.accept()
print 'Connected by', addr
# loop reading/echoing, until client disconnects
try:
    conn.send("Send me data, and I will echo it back after a short delay.\n")
    while 1:
        data = conn.recv(1024)                          # recv all data queued
        if not data: break                              # client disconnected
        time.sleep(3)                                   # simulate time consuming work
        # below will detect if client disconnects during sleep
        r, w, e = select.select([conn], [], [], 0)      # more data waiting?
        print "select: r=%s w=%s e=%s" % (r,w,e)        # debug output to command line
        if r:                                           # yes, data avail to read.
            t = conn.recv(1024, socket.MSG_PEEK)        # read without remove from queue
            print "peek: len=%d, data=%s" % (len(t),t)  # debug output
            if len(t)==0:                               # length of data peeked 0?
                print "Client disconnected."            # client disconnected
                break                                   # quit program
        conn.send("-->"+data)                           # echo only if still connected
finally:
    conn.close()
1
ответ дан user 26 August 2018 в 20:38
поделиться

Это очень легко сделать: надежный и не беспорядочный:

        Try
            Clients.Client.Send(BufferByte)
        Catch verror As Exception
            BufferString = verror.ToString
        End Try
        If BufferString <> "" Then
            EventLog.Text &= "User disconnected: " + vbNewLine
            Clients.Close()
        End If
84
ответ дан user207421 26 August 2018 в 20:38
поделиться
Другие вопросы по тегам:

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