Синхронизация потоков в клиент-серверном приложении? - PullRequest
0 голосов
/ 12 марта 2012

Я работал над приложением для загрузки файлов, где сервер непрерывно ожидает новых запросов на подключение от клиентов, когда приходит новое подключение, сервер принимает это подключение и создает новый процесс для обслуживания клиента, недавно подключенного к серверу.Клиенты могут запросить загрузку нескольких файлов с сервера.Для каждого файла стороны клиента и сервера создают новый поток, и передача данных для каждого файла должна выполняться между соответствующими парами потоков сервера и клиента.Я использую C и pthread для потоков.У меня сейчас стабильное сокетное соединение и успешное создание процесса для каждого клиента.

Для потокового файлового трансфера я попытался сделать следующее:

В клиенте я создаю потоки, которые запускают метод для получения файлов:

        int k;
        for (k = 0; k < fNameCounter; k++)
        {
            pthread_t thread_id;
            int status = pthread_create(&thread_id, NULL, &receiveFile, fName );

            if (status != 0)
            {
                printf("Thread Creation Failed \n");
                exit(0);
            }
        }

Аналогично вна стороне сервера, я создаю такое же количество потоков, как показано ниже:

        int k;
        for (k = 0; k < fnameCounter; k++)
        {
            pthread_t thread_id;
            int status = pthread_create(&thread_id, NULL, &sendFile, fName );

            if (status != 0)
            {
                printf("Thread Creation Failed \n");
                exit(0);
            }
        }

Функции sendFile и receiveFile просто записывают и считывают байты файлов, указанных в fName (как вы можете видеть в pthread_create) по сокету, в этот моментУ меня есть серьезная проблема:

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

Как я могу гарантировать, что каждый поток клиента получает правильные данные из соответствующего потока сервера, как я объяснил ниже:

        receive         send

cthread1 ---->  a.txt  <-----   sthread1

cthread1 ---->  a.txt  <-----   sthread1

cthread1 ---->  a.txt  <-----   sthread1

ps Мне известно, что при создании многих потоководин сокет не имеет смысла, но это мой hw, и мне нужно сделать так: /.

С уважением.

Ответы [ 3 ]

1 голос
/ 12 марта 2012

Самый простой способ - открыть новый сокет для каждого файла.

0 голосов
/ 12 марта 2012

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

Например, sthread1 отправит 100 байтов из файла a.txt. Вы можете добавить один байт в начало этого потока, содержащий число 1. При получении этого фрагмента данных, cthread1 должен проверить первый байт: если он равен 1, тогда все в порядке, этот блок предназначен для cthread1, продолжайте обработку. Если заголовок не 1, то cthread1 должен игнорировать этот чанк и продолжать ждать, предоставляя другим потокам возможность работать тоже.

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

Обратите внимание, что это добавляет много сложности для решения:

  1. Вам нужно решить, как назначить эти идентификаторы для ваших пар потоков
  2. Если вы используете только один байт, имейте в виду, что максимальное значение, которое он содержит, составляет 255.
  3. Возможно, вам придется использовать флаг MSG_PEEK в вашей функции recv внутри cthread (так что вы можете игнорировать блок при необходимости). Этот флаг изменяет поведение функции recv. Я советую вам прочитать это (если вы программируете на Win) или это (если вы используете Linux).
0 голосов
/ 12 марта 2012

Для завершения zvrba очень допустимая точка (один сокет, один файл).

Я думаю, что темы здесь бесполезны: у вас есть одна сетевая карта. Вы не получите быстрее, прослушивая один и тот же ресурс несколько раз. Вы, скорее всего, заставите свои потоки блокировать друг друга и будете на самом деле медленнее.

Если вы хотите оставить отзыв пользователю, то вы можете создать один фоновый поток для всех операций ввода-вывода сокета.

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

...