Это очень распространенная проблема, с которой мы сталкиваемся, борясь с «таинствами» 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
значение (которое вы намерены вернуть). Таким образом, короче говоря, вы разрешаете значение вместо возврата в асинхронных функциях.
select (с набором маски чтения) вернется с указателем на маркер, но если вы используете ioctl * для проверки количества байтов, ожидающих чтения, оно будет равно нулю. Это признак того, что сокет был отключен.
Это отличная дискуссия по различным методам проверки того, что клиент отключился: Стивен Клири, обнаружение полуоткрытых (отброшенных) соединений .
* для Windows использовать ioctlsocket.
Возвращаемое значение приема будет равным -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();
}
}
Попробуйте найти EPOLLHUP или EPOLLERR. Как проверить соединение с клиентом все еще жив
Чтение и поиск 0 будут работать в некоторых случаях, но не во всех.
Я играл с несколькими решениями, но этот, похоже, лучше всего подходит для обнаружения отключения хоста и / или клиента в 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;
}
Если вы используете перекрывающиеся (то есть асинхронные) операции ввода-вывода с процедурами завершения или порты завершения, вы будете немедленно уведомлены (при условии, что у вас есть прочитанное сообщение), когда клиентская сторона закрывает соединение.
Этот вопрос основан на различных заблуждениях относительно сетевого стека.
Прежде всего, нет понятия «соединение» Tcp или иначе, и чем раньше вы сделаете это различие, тем скорее вы поймете, что это ничем не отличается от udp или любого другого протокола.
Когда вы получаете время, у вас либо есть данные для отправки, либо нет.
Если вы не хотите передавать, чем, необязательно увеличивайте время ожидания и получаете снова.
Если клиент отключил компьютер или иным образом отключился, то как и почему это имеет значение?
Разве это сломает ваше «соединение»? Может быть, но, возможно, нет, кто знает, как настроен ваш компьютер или LSP.
Обычный способ сделать это аналогичен любым другим протоколам, и я напоминаю вам, что сокет уже «подключен», в случаях, когда происходит регенерация.
Когда вы пытаетесь отправить этому клиенту что-то, что вы узнаете, если клиент «подключен» или более правильно подтвердил ваши данные под Tcp. (В udp также зависит от сети через icmp)
Почему вы проголосовали за этот ответ из-за своего собственного недоразумения.
Короче говоря, если у вас есть данные для отправки отправки и определения того, какое действие требуется после отправки или неудачи.
Если время срабатывания вашей приемки одинаково, и, при желании, вы можете использовать отправку размера 0, чтобы подтвердить, что другая сторона все еще принимает ваши данные.
TCP имеет «открытые» и «закрытые» процедуры в протоколе. После «открытия» соединение удерживается до «закрытого». Но есть много вещей, которые могут остановить поток данных ненормально. При этом методы определения того, можно ли использовать ссылку, сильно зависят от уровней программного обеспечения между протоколом и прикладной программой. Те, о которых упоминалось выше, сосредоточены на программиста, пытающегося использовать сокет неинвазивным способом (чтение или запись 0 байтов), возможно, являются наиболее распространенными. Некоторые слои в библиотеках будут предоставлять «опрос» для программиста. Например, вызовы Win32 asych (delayed) могут начать чтение, которое будет возвращаться без ошибок и 0 байтов, чтобы сигнализировать сокет, который больше не может быть прочитан (предположительно, процедура TCP FIN). В других средах могут использоваться «события», как определено в их обертывающих слоях. На этот вопрос нет единого ответа. Механизм обнаружения, когда сокет не может использоваться и должен быть закрыт, зависит от оберток, поставляемых в библиотеках. Также стоит отметить, что сами сокеты могут быть повторно использованы слоями под библиотекой приложений, поэтому разумно разобраться, как ваша среда работает с интерфейсом Berkley Sockets.
Чтобы увеличить это немного:
Если вы используете сервер, вам нужно либо использовать TCP_KEEPALIVE для мониторинга клиентских подключений, либо сделать что-то подобное себе, либо иметь знания о данных / протоколе что вы работаете над соединением.
В принципе, если соединение будет убито (т. е. неправильно закрыто), то сервер не заметит, пока он не попытается что-то написать клиенту, что является то, что keepalive для вас. В качестве альтернативы, если вы знаете протокол лучше, вы можете просто отключиться от таймаута бездействия.
Мы столкнулись с подобной проблемой, когда обнаружение удаления кабеля на ПК было проблемой. После googling мы попали в SuperCom для библиотеки TCP, которая предложила эту функцию и очень надежную библиотеку передачи данных, которая также могла обрабатывать события отчетности, когда соединение было закрыто.
apr-библиотека из проекта apache является хорошей ссылкой для этой проблемы. Он использует опрос с тайм-аутом, чтобы проверить, нарушено ли соединение другой стороны.
"""
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()
Это очень легко сделать: надежный и не беспорядочный:
blockquote>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