broken TCP/IP socket

Модератор: Модераторы разделов

Аватара пользователя
cy6erGn0m
Сообщения: 119
ОС: MandrivaLinux/Solaris 10

broken TCP/IP socket

Сообщение cy6erGn0m »

Есть следующая проблема и вот его проявления:
1. есть некоторое большое приложение (не мною писаное)
2. оно открывает TCP/IP соединение и читает из сокета с помощью recv
3. читает таким образом что блокируется до тех пор пока не придут данные (без таймаута чтения)
4. Если соединение неожиданно обрывается ( как я понимаю соединения обрывается по инициативе удалённой машины ввиду отсутствия взаимодействия ) то чтение продолжает висеть .. я не могу раскопать всех частей приложения но само чтение выглядит примерно так:

Код: Выделить всё

    int ret;
    threadEntry_t self;
    fdEntry_t *fdEntry = getFdEntry(s);
    if (fdEntry == NULL) {
        errno = EBADF;
        return -1;
    }
    do {
        startOp(fdEntry, &self);
        ret = recv(s, buf, len, 0);
        endOp(fdEntry, &self);
    } while (ret == -1 && errno == EINTR);
    return ret;


Вопрос: может ли быть такое чтобы recv не возвращал управление при каких-то флагах установленных для сокета? может ли быть такое чтобы при обрыве этот цикл зациклился?

Ситуация усложняется тем что я не знаю какой именно тип обрыва произошёл (пришёл ли TCP-пакет на обрыв или же просто удалённая машина "замолчала")

Внешние проявления таковы что приложение не заметило что сокет оборвался.

Может кто сталкивался с таким?



И к этому коду коммент:

Код: Выделить всё

 * perform a blocking IO operation. Restarts
 * automatically if interrupted by signal (other than
 * our wakeup signal)
I want to Believe!

They must find it difficult...
Those who have taken authority as the truth,
Rather than trusth as the authority.
/G.Messey/
Спасибо сказали:
Аватара пользователя
GRS
Сообщения: 236
Статус: C++ Pro
ОС: Suse10.2/XP

Re: broken TCP/IP socket

Сообщение GRS »

Вставь текстовые трапы в цикл (типа printf("i am in cycle, ret = %d, errono =%d", ret, errno);
Посмотри что будет выводится.
Вообще конструкция бредовая - т.е. цикл работает пока у тебя ошибка соединения (как только ошибок не будет - произойдет выход из цикла).
Собственно поэтому и не выходит, он продолжает работать пока данные не придут.

Кроме того ret == -1, это не правильно ret может быть и 0 равно - что будет означать окончание передачи данных. Хотя насчет этого я точно не уверен, уже давно с чистыми сокетами дела не имел, нужно вспомнить ... хотя все равно я всегда писал неблокируемые сокеты, потому блокируемый ввод/вывод - непонятно кому он нужен.

Код конечно просто ламерский ... один цикл do/while - уже говорит об "умении" этого программиста, который до тебя код писал. Еще бы хорошо увидеть что внутри EndOp - потому как непонятно откуда берутся значения errno. Судя по всему где-то там внутри.
Спасибо сказали:
Аватара пользователя
cy6erGn0m
Сообщения: 119
ОС: MandrivaLinux/Solaris 10

Re: broken TCP/IP socket

Сообщение cy6erGn0m »

Да, я не предупредил: в нормальной ситуации это отлично работает без нареканий. Проблемы возникают если оставить это надолго и в течение долго времени нет обмена и видимо на том конце сочли что надо бы сокет прикрыть.. и видим сделали это втихаря. Если явно приходит пакет на обрыв, то он всё же прерывается. Застревает в каком-то очень редком случае который мне не повторить.

Код: Выделить всё

static inline void endOp
    (fdEntry_t *fdEntry, threadEntry_t *self)
{
    int orig_errno = errno;
    pthread_mutex_lock(&(fdEntry->lock));
    {
        threadEntry_t *curr, *prev=NULL;
        curr = fdEntry->threads;
        while (curr != NULL) {
            if (curr == self) {
                if (curr->intr) {
                    orig_errno = EBADF;
                }
                if (prev == NULL) {
                    fdEntry->threads = curr->next;
                } else {
                    prev->next = curr->next;
                }
                break;
            }
            prev = curr;
            curr = curr->next;
        }
    }
    pthread_mutex_unlock(&(fdEntry->lock));
    errno = orig_errno;
}


На мой взгляд застревает если удалённая машина просто замолкает. Но в документаци на recv не написано что в такой ситуации будет. Что касается бесконечного чтения из сокета - это реально необходимо, потому что данные могут прийти в любой момент. Протокол устроен таким образом, что данные просто приходят, их не надо запрашивать.
I want to Believe!

They must find it difficult...
Those who have taken authority as the truth,
Rather than trusth as the authority.
/G.Messey/
Спасибо сказали:
Аватара пользователя
cy6erGn0m
Сообщения: 119
ОС: MandrivaLinux/Solaris 10

Re: broken TCP/IP socket

Сообщение cy6erGn0m »

И ещё: а не может такого быть что дело не в этом коде? может это само ядро не замечает потери связи и поэтому не возвращает никакую ошибку?
I want to Believe!

They must find it difficult...
Those who have taken authority as the truth,
Rather than trusth as the authority.
/G.Messey/
Спасибо сказали: