Имеется следующий код://Код, подготовливающий сокет, для прослушивания подключений.
...
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), то при каждом подключении выделятся новый сокет.
>Имеется следующий код:
[...]
>И вот в этой ситуации Подключение 1 продолжает работать, а больше никакие
>подключения не принимаются, как будто завершается основной процесс.А он действительно завершился? В смысле, что говорит ps?
Ничего противоестественного в коде не вижу (кроме, разве что, экономии
на break, что не страшно, хотя и подозрительно); ошибка, скорее всего,
где-то в деталях. Попытайтесь воспроизвести ситуацию на минимальном
коде и пришлите что-нибудь компилируемое. Без отладчила такие проблемы
ох как трудно решать.>И еще непонятка:
>Допустим, при подключении 1 выделяется сокет 4; затем при подключении 2 выделяется
>опять-же сокет 4. Почему так происходит? Хотя если убрать строки с
>close(CSocket), то при каждом подключении выделятся новый сокет.Так и должно быть. Для того CSocket и закрываем. Был дескриптор 4 занят,
сказали close и он освободился; можно снова занимать. Если вам удастся
сделать второе подключение до close в первом, получите fd 5.
Ну вообще-то получалось делать два подключения до close (Ситуация 2). И в обеих случаях CSocket равен 4.
А завершился основной процесс или нет - я незнаю. Это мое предположение.
ps немогу запустить, т. к. работает моя программа.
Результаты некоторых экспериментов:Вот так изменил немного код:
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.
Так вот, основной процесс не убивается!!!
Я разобрался с глюком!!!Для того, чтобы удалять процессы-зомби я из умной книги содрал следующий код:
Перед 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); - не помагает.