powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / сокет уже "не живой"
11 сообщений из 11, страница 1 из 1
сокет уже "не живой"
    #39571859
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверяю состояние сокета через WaitForData.
Я, конечно же, прочитал коммент, что
Код: pascal
1.
// Select also returns True when connection is broken.


в связи с чем, возникает вопрос - как определить, что сокет уже "не живой"?
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571861
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и чтобы без таймаута.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571875
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cobalt747в связи с чем, возникает вопрос - как определить, что сокет уже "не живой"?
Рекомендую иногда заглядывать на SO, там можно найти уже готовые ответы на многие вопросы:
https://stackoverflow.com/questions/685951/how-can-i-check-if-a-client-disconnected-through-winsock-in-c if you call recv in blocking mode and it returns with 0 bytes read, the socket has disconnected, else it wait for bytes to be received.

Т.е. если вы после WaitForData смогли прочитать только 0 байт или recv вернул SOCKET_ERROR с ошибкой WSAECONNRESET, то сокет был закрыт. Разные результаты, как я понимаю, зависят от того как именно было закрыто соединение: тупо разорвана связь или именно "закрыто" другой стороной (насчёт последнего я, правда, не уверен на 100%, необходимо проверять).
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571897
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В том-то и дело, что хочу избежать такой ситуации:
авторelse it wait for bytes to be received.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571960
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpТ.е. если вы после WaitForData смогли прочитать только 0 байт или recv вернул SOCKET_ERROR с ошибкой WSAECONNRESET, то сокет был закрыт

Я так понимаю, что WaitForData - это select. И если он вернет 0, и recv не вернет SOCKET_ERROR, то он повиснет намертво, пока не прочитает то, что надо.
Правда, не знаю, что будет, если передать в recv длину 0. Скорее всего, он всегда сразу будет возвращать 0, это логично.
Речь о блокирующих сокетах.

Cobalt747как определить, что сокет уже "не живой"?
Это делается с помощью select.

Вот что-то подобное:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
function WaitForData( Socket: TSocket ): Integer;
const
  WAIT_DATA_TIMEOUT = 50; // Можешь поставить 0 - не рекомендую, будет еще более не точно.
var
  FDSet, FDSetE: TFDSet;
  TimeVal: TTimeVal;
  nErr, nOptLen: Integer;
begin
  TimeVal.tv_sec := WAIT_DATA_TIMEOUT div 1000;
  TimeVal.tv_usec := ( WAIT_DATA_TIMEOUT mod 1000 ) * 1000;

  FDSet.fd_count := 1;
  FDSet.fd_array[ 0 ] := Socket;

  FDSetE.fd_count := 1;
  FDSetE.fd_array[ 0 ] := Socket;

  Result := select( 0, @FDSet, nil, @FDSetE, @TimeVal );
  if Result < 0 then begin
    Result := SOCKET_ERROR;
    Exit;
  end;

  if FD_ISSET( Socket, FDSetE ) then begin
    nOptLen := sizeof( nErr );
    if SOCKET_ERROR = getsockopt( Socket, SOL_SOCKET, SO_ERROR, @nErr, nOptLen ) then
      nErr := WSAENOTCONN;

    WSASetLastError( nErr );
    Result := SOCKET_ERROR;
  end;
end;


Ну и вот:
1. Если WaitForData вернула > 0 - значит есть данные для чтения;
2. Если WaitForData вернула = 0 - значит нет данных для чтения, но сокет "живой" ;
3. Если WaitForData SOCKET_ERROR - значит всё, можешь вызывать WSAGetLastError/SysErrorMessage, если надо.

И, конечно, сокет может умирать далеко не сразу. Может через десятки секунд, минуты (после того, как где-то шнурок перетыкнут). А ты говоришь, без таймаута.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571963
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, и если WaitForData вернул > 0, то recv потом тоже может SOCKET_ERROR вернуть - это тоже надо проверять.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39571971
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cobalt747В том-то и дело, что хочу избежать такой ситуации:
авторelse it wait for bytes to be received.
Я исходил из этого: If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero .
....
For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified.
Т.е. предполагается, что если select (WaitForData) показал наличие данных для чтения, то и первый после него вызов recv тоже не должен блокироваться.

Что мешает проверить экспериментально? :)
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39572329
Фотография Maxim Rusov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cobalt747как определить, что сокет уже "не живой"?
Никак.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39572361
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim RusovCobalt747как определить, что сокет уже "не живой"?
Никак.Не, ну в общем случае, конечно, никак, но со временем эту информацию можно получить. Особенно, если логика построена таким образом, что либо recv постоянно висит, либо в промежутках между этими "висениями" send отправляет.
Так мне больше всего ошибку получать нравится.
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39572512
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Это не та задача что передо мной стоит.

Мне надо различать:
1) отсутствие данных от сервера
2) разрыв связи с сервером.

Причем я не хочу висеть на коннекте, блокируя поток.

Пока что вышел из положения, задав SO_RCVTIMEO
...
Рейтинг: 0 / 0
сокет уже "не живой"
    #39572557
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cobalt747alekcvp,

Это не та задача что передо мной стоит.

Мне надо различать:
1) отсутствие данных от сервера
2) разрыв связи с сервером.

Причем я не хочу висеть на коннекте, блокируя поток.
Ну так в чём проблема: сначала делаешь select с readfds, для проверки сокета. Если результат 0 - нет данных для чтения, если 1 - либо есть данные, либо дисконнект, если SOCKET_ERROR - значит ошибка.
Во втором случае (select() = 1) делаешь recv() один байт с флагом MSG_PEEK, если он вернёт 0 или ошибку - значит дисконнект, если больше - значит есть данные для чтения. При этом данные никуда не денутся.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / сокет уже "не живой"
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]