The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Непонятки с fork() в UNIX....."
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Непонятки с fork() в UNIX....."
Сообщение от Cker Искать по авторуВ закладки on 02-Ноя-02, 17:11  (MSK)
Имеется следующий код:

    //Код, подготовливающий сокет, для прослушивания подключений.
    ...
    while (1)
      {
        bzero(&clnt_addr, sizeof(clnt_addr));
        addrlen=sizeof(clnt_addr);

        CSocket=accept(SSocket, (struct sockaddr *)&clnt_addr, &addrlen);
        if (CSocket<0)
          printf("Error accept()\n");
        else
          {          
            switch (fork())
              {
                case 0:
                        close(SSocket);
                        SomeFunc(CSocket, inet_ntoa(clnt_addr.sin_addr));
                        close(CSocket);
                        exit(0);
                case -1:
                         printf("Error fork()\n");
                default:
                         close(CSocket);
              }
          }
      }

Примерное содержимое функции SomeFunc

int SomeFunc(....)
  {
    ....
    
    //блок А, по выполнению которого в любом случае в конце вызывается return 0

    //блок Б, представляющий из себя бесконечный цикл

  }


Ситуация 1:
Подключение 1 с выходом по блока А
Подключение 2 с выходом по блоку А
Все работает Ок.

Ситуация 2:
Подключение 1 с зацикливанием по блоку Б
Подключение 2 с зацикливанием по блоку Б
Все работает Ок.

Ситуация 3:
Подключение 1 с зацикливанием по блоку Б
Подключение 2 с выходом по блоку А
И вот в этой ситуации Подключение 1 продолжает работать, а больше никакие подключения не принимаются, как будто завершается основной процесс.
???

И еще непонятка:
Допустим, при подключении 1 выделяется сокет 4; затем при подключении 2 выделяется опять-же сокет 4. Почему так происходит? Хотя если убрать строки с close(CSocket), то при каждом подключении выделятся новый сокет.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "RE: Непонятки с fork() в UNIX....."
Сообщение от vnp emailИскать по авторуВ закладки on 02-Ноя-02, 23:19  (MSK)
>Имеется следующий код:
[...]
>И вот в этой ситуации Подключение 1 продолжает работать, а больше никакие
>подключения не принимаются, как будто завершается основной процесс.

А он действительно завершился? В смысле, что говорит ps?

Ничего противоестественного в коде не вижу (кроме, разве что, экономии
на break, что не страшно, хотя и подозрительно); ошибка, скорее всего,
где-то в деталях. Попытайтесь воспроизвести ситуацию на минимальном
коде и пришлите что-нибудь компилируемое. Без отладчила такие проблемы
ох как трудно решать.

>И еще непонятка:
>Допустим, при подключении 1 выделяется сокет 4; затем при подключении 2 выделяется
>опять-же сокет 4. Почему так происходит? Хотя если убрать строки с
>close(CSocket), то при каждом подключении выделятся новый сокет.

Так и должно быть. Для того CSocket и закрываем. Был дескриптор 4 занят,
сказали close и он освободился; можно снова занимать. Если вам удастся
сделать второе подключение до close в первом, получите fd 5.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "RE: Непонятки с fork() в UNIX....."
Сообщение от Cker Искать по авторуВ закладки on 03-Ноя-02, 00:26  (MSK)
Ну вообще-то получалось делать два подключения до close (Ситуация 2). И в обеих случаях CSocket равен 4.
А завершился основной процесс или нет - я незнаю. Это мое предположение.
ps немогу запустить, т. к. работает моя программа.
  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "RE: Непонятки с fork() в UNIX....."
Сообщение от Cker Искать по авторуВ закладки on 03-Ноя-02, 23:17  (MSK)
Результаты некоторых экспериментов:

Вот так изменил немного код:

    while (1)
      {
        bzero(&clnt_addr, sizeof(clnt_addr));
        addrlen=sizeof(clnt_addr);

        CSocket=accept(SSocket, (struct sockaddr *)&clnt_addr, &addrlen);
        if (CSocket<0)
          printf(String, "Error accept()");
        else
          {
            
            sprintf(String, "New connect (%d). IP=%s", CSocket, inet_ntoa(clnt_addr.sin_addr));
            printf("%s", String);
            switch (fork())
              {
                case 0:
                        close(SSocket);
                        Result=read(CSocket, Buffer, sizeof(Buffer));
                        if (Result<0)
                          printf("Error read");
                        else printf(Buffer);
                        close(CSocket);
                        exit(0);
                        break;
                case -1:
                         printf("Error fork()\n");
                         break;
                default:
                         close(CSocket);
                         break;
              }
          }
      }

т. е. после того, как клиент что-нибудь присылает, связь с ним разрывается и процесс уничтожается.

Есть клиент, написанный на делфи. По нажатию на кнопку "Button1" происходи соединение с сервером. По нажатию на "Button2" происходит отправка серверу строки "Proverka".

Такие результаты экспериментов (результаты вывожу в виде тех строк, которые отображаются на экране функциями printf):

Запускаю три копии клиентов.
Подключение клиентом 1: New connect (4) IP=192.168.0.1
Подключение клиентом 2: New connect (4) IP=192.168.0.2
Отправка клиентом 1: Proverka
Подключение клиентом 3: Никакого текста не выводится!!!!!
//разрыв - для описания далее
Отправка клиентом 2: ProverkaNew connect (4) 192.168.0.1

Т. е. после того, как произошел разрыв хотя-бы с одним клиентом, новое соединение "не принимается".
И лишь после того, как разорвалась связь со всеми предыдущими клиентами - происходит связь с новым клиентом.???

И что еще интерестно, если в разрыв вставить:
Отправка клиентом 3; Отправка клиентом 3; Отправка клиентом 3;
т. е. три раза отправить третим клиентом, то получается следующее (текст для замены после разрыва):
Отправка клиентом 2: ProverkaNew connect (4) 192.168.0.1
ProverkaProverkaProverka


Т. е., как я понимаю, клиент три раза отправляет, т. к. со стороны сервера соединение не разорвано. И лишь после приема соединения принимаются все три пакета.

Вот так. Надеюсь, Вы поняли то, что я хотел сказать.

И еще: запускал свою прогу как демона и смотрел список процессов утилиткой ps.
Так вот, основной процесс не убивается!!!


  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "RE: Непонятки с fork() в UNIX....."
Сообщение от Cker Искать по авторуВ закладки on 05-Ноя-02, 23:33  (MSK)
Я разобрался с глюком!!!

Для того, чтобы удалять процессы-зомби я из умной книги содрал следующий код:

Перед while(1)
(void) signal(SIGCHLD, reaper);

и соответственно есть функция:
void reaper(int sig)
  {
    int status;

    while (wait3(&status, WNOHANG, (struct rusage *)0)>=0)
      ;
  }


Так вот, если  закоментировать строку:
//(void) signal(SIGCHLD, reaper);

то все начинает работать как часы, только процессы-зомби плодятся и неуничтожаются.

Как бы это исправить?
signal(SIGCHLD, SIG_IGN); - не помагает.

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру