LINUX.ORG.RU

сокеты и wait()


0

0

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

Вот в чём проблема: если я убиваю дочерний процесс, далее wait(&status); то всё нормально: сокеты вновь создаются и всё работает, но если я не убиваю дочерний процесс, а просто закрываю сокеты, потом их вновь создаю, то вылезает ошибка при вызове bind: perror выводит: Address already in use. То есть порт занят. Но ведь я закрыл сокет! Даже shutdown(sock, SHUT_RDWR) вызвал для него!

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

anonymous

Re: сокеты и wait()

1. setsockopt(...SO_REUSEADDR...) -- может, хватит, если shutdown() сделал; не уверен

2. А дочка дескриптор закрыла?

Die-Hard ★★★★★ ()

Re: сокеты и wait()

почитай архив. тема не раз обсуждалась.

решается флагами кажись для socket()

cvv ★★★★★ ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

Дочка сокет не закрывает, но и не использует эти сокеты (создаёт другой). Как я понял, close закрывает сокет и для дочерних процессов. Сейчас попробую setsockopt...

anonymous ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

> setsockopt(...SO_REUSEADDR...) -- может, хватит, если shutdown() сделал; не уверен

Факт. Все будет хорошо.

anonymous ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

anonymous (*) (23.09.2005 15:19:43):

> Как я понял, close закрывает сокет и для дочерних процессов

Без shutdown -- ни разу.

Die-Hard ★★★★★ ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

Это опять я. Не помогает setsockopt! Вставил в код следующие строки: int sval=0; ......... if((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sval, 4))<0) perror("setsockopt");

тот же глюк

закрытие сокетов частично помогло: Теперь сервер перезапускается при отсутствии соединений, но как только клиент соединяется с к-л портом, всё, порт занят, и при перезапуске блокируется. Хотя я его закрываю.

Получается вот что: пока к сокету не обратились, он перезапускается, после обращения - блокируется.

P.S. Я не мог наврать в setsockopt?

anonymous ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

anonymous (*) (23.09.2005 17:07:16)

>Я не мог наврать в setsockopt?

Правильно (только за "&sval, 4" надо кое-что отрывать! )

Давай сюда логику поподробнее

Die-Hard ★★★★★ ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

функция создаёт серверный сокет (здесь возникает ошибка bind):

int sock;
struct sockaddr_in echoServAddr;
int sval=0;

if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ErrorExit("socket() failed");

....
здесь устанавливаем поля структуры
....

if((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sval, 4))<0) perror("setsockopt");
.....

if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
{
fprintf(stderr, "%d", port);
ErrorExit("bind() failed");
}

далее listen, он работает нормально
}

в main при коннекте порождаются процессы:
for (arm = 0; arm < aset.armcount; arm++)
if (FD_ISSET((aset.armarray)[arm].servSock, &sockSet))
{
if ((processID = fork()) < 0)ErrorExit("fork() failed");
else if (processID == 0)
{
HandleClient(&((aset.armarray)[arm]));
exit(0);
}
}

В HandleClient
вызываем accept, получаем clientSock, работаем с ним, закрываем
серверный сокет не трогаем. Я убрал закрытие сокетов в дочерних процессах - ничего не изменилось. Наверное, не в close дело...


anonymous ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

Поправил:
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sval, sizeof(int)))
В дочернем процессе я закрываю теперь все сокеты, но это не помогает после подключениия клиента
Не помог даже wait4 - пытался собрать все pid в массив, в цикле вызывать wait4:

for (i= 0; i < proc_count; i++){
wait4(Array_ID[proc_count], &status, WNOHANG, NULL);
}
free(Array_ID);
Array_ID=NULL;
proc_count=0;

anonymous ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

Ухожу с работы, буду за компом вечером.
Благодарю за помощь, напиши если увидишь глюк

anonymous ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

2anonymous (23.09.2005 19:23:44)

Я тоже скоро ухожу, и, наверное, до понедельника.

Попробуй логику чуть подробнее сюда прислать -- может, кто подскажет. На выходных тут много народу околачивается...

Die-Hard ★★★★★ ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

Проверь, что дочка точно закрывает сокеты (через /proc/PID/fd).

Посмотри netstat'ом состояние создоваемых тобой сокетов.

Может в цикле перестарта демона попробовать ввести задержку?

>в main при коннекте порождаются процессы

В этих процессах, вроде надо тоже закрывать лишние сокеты...

Насчет wait4(), ИМХО лучше делать wait4(-1) и если wait4() сказал, что процесс завершился, искать его pid в Array_ID.

mky ★★★★★ ()
Ответ на: Re: сокеты и wait() от mky

Re: сокеты и wait()

Для дочки в /proc/PID/fd нет доступа, она всё закрывает, но кажется не в этом дело.
Вот что выяснил: если просканировать порты (пользовался Nmap), то порождается куча дочерних процессов, но сервер перезапускается, при том, что дочерние процессы при этом ничего не закрывают.
Порт блокируется, если использовался для передачи данных, даже если был закрыт.

if ((processID = fork()) < 0)ErrorExit("fork() failed");
else if (processID == 0) /* If this is the child process */
{
printf("Request on port %d: ", (aset.armarray)[arm].client_port);
HandleClient(&((aset.armarray)[arm])); - вылетает при сканировании
close(resetSock);
for (arm = 0; arm < aset.armcount; arm++)
{
close((aset.armarray)[arm].servSock);
}
exit(0); /* Child process terminates */

Вылетает из-за этого:
access_flag=access_flag & AcceptTCPSocket(arm_data);
if(access_flag) access_flag=access_flag & check_MAC(arm_data);
if (access_flag) answptr=answstr7;
else {
answptr=answstr8;
printf(answptr);
}
send_data((*arm_data).clientSock, answptr);

В функции send_data выполняется exit, если send не выполнен
Вопрос: что происходит с сокетом после использования?
Он не отцепляется от порта даже после закрытия

anonymous ()
Ответ на: Re: сокеты и wait() от mky

Re: сокеты и wait()

Решил проблему:
Оказывается, порт освобождается не сразу, поэтому изменил алгоритм создания сокетов:

/* Create port socket */
i=0;
while(1)
{
(aset.armarray)[arm].servSock = CreateTCPServerSocket((aset.armarray)[arm].client_port);
if((aset.armarray)[arm].servSock!=0) break;
sleep(10);
i++;
if(i>20){running=0; break;}
}

функция создания сокета теперь при неудаче возвращает 0 (а не делает exit)
сокет подключается с 4-5 попыток (причём какой-то один, остальные без задержки)
теперь всё работает, только где-то минута требуется на перезапуск (из-за ожидания)

anonymous ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

>Оказывается, порт освобождается не сразу

Это известная истина. По всей видимости ты для какогото порта не делаеш setsockopt(...SO_REUSEADDR...)

cvv ★★★★★ ()
Ответ на: Re: сокеты и wait() от cvv

Re: сокеты и wait()

Согласен с cvv:

> По всей видимости ты для какогото порта не делаеш setsockopt(...SO_REUSEADDR...)

Типичные симптомы.

Die-Hard ★★★★★ ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

Нет, setsoskopt делается:


if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ErrorExit("socket() failed");
................
if((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sval, sizeof(int)))<0) perror("setsockopt");

if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) <0)
{
printf("port %d busy\n", port);
close(sock);
return 0;
}

Но не помогает.

anonymous ()
Ответ на: Re: сокеты и wait() от anonymous

Re: сокеты и wait()

2 автор топика:

Посыпаю голову пеплом и закапываю ее в песок от стыда! Ты спрашивал про это, а я почему-то проглядел...

int sval=0; ... setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sval, 4);

неверно, надо sval=1.

Die-Hard ★★★★★ ()
Ответ на: Re: сокеты и wait() от Die-Hard

Re: сокеты и wait()

Всё работает, задержка исчезла!!!
Благодарю за помощь

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.