Проблема с сокетами в *nix

Рейтинг: 1Ответов: 1Опубликовано: 02.06.2011

Сервер пишется на C, делает по потоку на каждое соединение. Приведу пример проблемы:

  1. Начинаю слушать порт, в ожидании новых подключений;
  2. Ко мне подключился клиент1 (файловый дескриптор сокета = 3) и присылает данные для обработки;
  3. Пока сервер пыхтит над данными, клиент по какой-то причине отключается;
  4. Подключается другой клиент2 (у него файловый дескриптор сокета тоже оказывается = 3!!);
  5. Сервер закончил обработку данных и начинает писать в файловый дескриптор сокета = 3, т.е, он думает что данные ушли клиенту1, а на самом деле клиенту2, который затем благополучной упал и дальше мясо...

Вообщем, проблема в том что если соединение разрывается (-1), то следующий подключившийся получит сокет с тем же файловым дескриптором(+1)...как с этим бороться?

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

Да, именно TCP.

P.S. подобная ситуация возникает даже при общении с обычными файлами, вот простой пример:

#include <stdio.h>
int main ()
{
    FILE * f = fopen("tmp.txt", "w");
    printf("descriptor1 = %d\n", fileno(f));
    fprintf(f, "some text");
    fclose(f);

    f = fopen("tmp.txt", "r");
    printf("descriptor2 = %d\n", fileno(f));
    fclose(f);

    return 0;
}

Результат:

descriptor1 = 3

descriptor2 = 3

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

Ответы

▲ 4Принят

Из Вашего примера можно сделать вывод, что Вы пытаетесь работать с клиентом по тому же сокету, который используете в accept().

Для общения с клиентом надо использовать сокет, возвращаемый accept(). См. man 2 accept