Сокеты и адресация
Модератор: Модераторы разделов
-
Tanatos
- Сообщения: 45
Сокеты и адресация
Есть сервер и клиент написанные мною (за основу взяты исходники из книги Ричард Стивенс UNIX Проффесиональное Программирование). Если оба приложения запустить на одном компьютере то соединение устанавливается и все отрабатывает замечателдьно. Зато если сервер и клиент на разных компьютерах клиент отказывается находить сервер. Функция getaddrinfo выдает сообщение "Servname not supported for ai_socktype". На сервере прописана следующая строчка в файле /etc/services "myserver 60200/tcp".
В чем может быть загвоздка?
Облазил интернет в поисках причин и решений но ответа так и не нашел.
Пробовал делать запись на клиенте в файле /etc/services - сообщение об ошибке получал такое: "Name or service not known".
Как правильно передать данные для сетевого соединения???
В чем может быть загвоздка?
Облазил интернет в поисках причин и решений но ответа так и не нашел.
Пробовал делать запись на клиенте в файле /etc/services - сообщение об ошибке получал такое: "Name or service not known".
Как правильно передать данные для сетевого соединения???
-
Rmic
- Сообщения: 87
- ОС: Linux
Re: Сокеты и адресация
А на стороне сервера вызывается функция bind?
А в чём смысл этого? Что значит "На сервере"? Вы имеете ввиду компьютер, где запускается программа-сервер?
На сервере прописана следующая строчка в файле /etc/services "myserver 60200/tcp".
А в чём смысл этого? Что значит "На сервере"? Вы имеете ввиду компьютер, где запускается программа-сервер?
Пингвин - друг человека!
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Да "сервером" в данном случае является просто компьютер на котором запущена соответствующая программа.
эта настройка осталась от локальных запусков, без нее не работало.
А вот что сделать чтобы через сеть программы друг друга видели ...
эта настройка осталась от локальных запусков, без нее не работало.
А вот что сделать чтобы через сеть программы друг друга видели ...
-
UTeHok
- Сообщения: 354
- Статус: Антиглобалист
- ОС: Debian GNU/Linux
Re: Сокеты и адресация
а порт точно открыт нак сервере?
Если открыт, сделайте какой-нить запрос из другой программы.
Если открыт, сделайте какой-нить запрос из другой программы.
«Make love, not war!»
-
GRS
- Сообщения: 236
- Статус: C++ Pro
- ОС: Suse10.2/XP
Re: Сокеты и адресация
ну для начала конечно нужно проверить, а пингуются ли вообще компьютеры.
так же не плохо бы написать каким образом продедура начала соединения на сервере и клиенте (src).
так же не плохо бы написать каким образом продедура начала соединения на сервере и клиенте (src).
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
По ip пингуется по имени хоста нет 
программу запускал и так и так, но раньше результат был одинаковым ... а сейчас если задать ip адрес просто висит на connect-е.
как проверить порт?
программу запускал и так и так, но раньше результат был одинаковым ... а сейчас если задать ip адрес просто висит на connect-е.
как проверить порт?
-
pcodr
- Сообщения: 283
- ОС: Debian
-
Tanatos
- Сообщения: 45
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: Сокеты и адресация
Эээ, а что это за утилита???
Код: Выделить всё
apt-cache search nmap
nmap - The Network MapperНу попробуй netcat
nc ip порт
Если порт закрыт он скажет чтото типа Connection refused иначе будет ожидать ввода команд. Еще может зависнуть если порт фильтруется фаерволом
remote system type is unix
-
Tanatos
- Сообщения: 45
-
UTeHok
- Сообщения: 354
- Статус: Антиглобалист
- ОС: Debian GNU/Linux
Re: Сокеты и адресация
а с локальной машины (это когда и то и то на одной тачке) клиент видет сервер???
«Make love, not war!»
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: Сокеты и адресация
Растолкуйте что это значит и как исправить ...
Это значит что твоя программа на сервере 192.168.1.143 не слушает порт под номером 60200
remote system type is unix
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Именно не слушает!? Странно ... программа запущенна и если запустить клиента на одной машине с сервером все отрабатывает.
В чем может быть загвоздка? Закрыт порт? Как тогда его открыть? Может где настройки надо прописать, только где и на какой из машин?
В чем может быть загвоздка? Закрыт порт? Как тогда его открыть? Может где настройки надо прописать, только где и на какой из машин?
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: Сокеты и адресация
Думаю нужно смотреть код сервера. Как уже говорили выше нужно убедиться что там присутствует bind на локальный порт 60200.
Еще убедться что коннектитесь к верному ip, а то мало ли.
Еще убедться что коннектитесь к верному ip, а то мало ли.
remote system type is unix
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Сокеты и адресация
Еще фаер может ресетить.
И серверный сорс покажите наконец. Мож там привязка к лупбэк адресу или еще какая напасть.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Обе машины это VMWare ... операционка Debian установка по умолчанию + samba + kdevelop + мелкие библиотеки
ip точно правильный, поскольку выделенные два ip на эти машины уникальны и прописывались ручками
Код сервера (ведение логов опущу):
ip точно правильный, поскольку выделенные два ip на эти машины уникальны и прописывались ручками
Код сервера (ведение логов опущу):
Код: Выделить всё
...
if(gethostname(host, MaxHostLen)<0)
exit(1);
hint.ai_flags = AI_CANONNAME;
hint.ai_family = 0;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if((err = getaddrinfo(host, "myserver", &hint, &ailist))!=0)
exit(1);
printf("Host: %s\n", host);
for(aip = ailist; aip != NULL; aip = aip->ai_next)
Net_Socket_FD = Net_Initialize(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN);
...
...
do
{
printf("Ожидаем соединения\n");
Net_Client_FD = accept(Net_Socket_FD, &Net_Client_Addr, &Net_Client_AddrLen);
if(Net_Client_FD<0)
exit(1);
...
if(Net_Client_FD>=0)
{
char Host[256];
socklen_t HostLen=256;
char Service[256];
socklen_t ServiceLen=256;
getnameinfo(&Net_Client_Addr, Net_Client_AddrLen, Host, HostLen, Service, ServiceLen, 0);
printf("Запрос на соединение\n");
printf(" Адрес клиента: %s - %s\n", Host, Service);
// Здесь идет некоторая работа и отправка ответа клиенту
while(fgets(buf, 128, fp) != NULL)
send(Net_Client_FD, buf, strlen(buf), 0);
printf("Ответ: %s", buf);
printf("Удерживаем соединение 10 сек\n");
sleep(10);
printf("Закрываем соединение\n");
close(Net_Client_FD);
printf("Прерываем рабочий цикл\n");
MainLoop = false;
}
}
while(MainLoop);
==============================================================
int Net_Initialize(int type, const struct sockaddr* addr, socklen_t alen, int qlen)
{
int fd;
int Reuse=1;
gLog->_Category_Net->info("Инициализация сокета...");
gLog->_Category_Net->info("Адрес: %s", addr->sa_data);
// Создаем сокет
if((fd=socket(addr->sa_family, type, 0))<0)
{
gLog->_Category_Net->error("Невозможно создать сокет");
return -1;
}
// Делаем сокет неблокирующим
//fcntl(fd, F_SETFL, O_NONBLOCK);
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &Reuse, sizeof(Reuse))<0)
{
gLog->_Category_Net->error("Ошибка вызова функции setsockopt");
return -1;
}
// Присваиваем адрес сокету
// Адрес должен быть зарегистрирован в файле "/ect/services"
if(bind(fd, addr, alen)<0)
{
gLog->_Category_Net->error("Ошибка вызова функции bind. Сокет закрыт.");
gLog->_Category_Net->info("Проверьте настройки файла etc/services");
close(fd);
return -1;
}
if(type==SOCK_STREAM || type==SOCK_SEQPACKET)
{
// Включаем прием запросов на подключение
if(listen(fd, qlen)<0)
{
gLog->_Category_Net->error("Ошибка вызова функции listen. Сокет закрыт.");
close(fd);
return -1;
}
}
gLog->_Category_Net->info("Инициализация сокета - Ok");
return fd;
}-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
IP верный, а вот насчет порта не уверен ... насколько я понимаю порт устанавливается на основании записи из /etc/services ... иначе откуда ему взяться ... в явном виде я его не указываю.
Кто ни будь знает, есть ли в Debian брендмауэр в установке по умолчанию и как проверить закрывает он порт или нет?
P.S.
Огромное спасибо всем кто отзывается на мои вопросы!!!
Кто ни будь знает, есть ли в Debian брендмауэр в установке по умолчанию и как проверить закрывает он порт или нет?
P.S.
Огромное спасибо всем кто отзывается на мои вопросы!!!
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Сокеты и адресация
Ну для эксперимента никто не мешает один раз и явно указать.
Кто ни будь знает, есть ли в Debian брендмауэр в установке по умолчанию и как проверить закрывает он порт или нет?
По-умолчанию он ставится голый как... (цензоред) И не думает об этом предупреждать, причем.
А проверить - вывод
Код: Выделить всё
iptables -Lпосмотреть/показать. (из-под рута)
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
sergio писал(а): ↑07.05.2008 12:25Кто ни будь знает, есть ли в Debian брендмауэр в установке по умолчанию и как проверить закрывает он порт или нет?
По-умолчанию он ставится голый как... (цензоред) И не думает об этом предупреждать, причем.
А проверить - вывод
Код: Выделить всё
iptables -L
посмотреть/показать. (из-под рута)
Результат таков:
Код: Выделить всё
Chain INPUT (policy ACCEPT)
target port opt source destinationТоже самое и для FORWARD и OUTPUT.
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Сокеты и адресация
Tanatos писал(а): ↑07.05.2008 13:00Результат таков:
Код: Выделить всё
Chain INPUT (policy ACCEPT) target port opt source destination
Тоже самое и для FORWARD и OUTPUT.
Все открыто, заходи кто хочешь бери что хочешь...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Добавил к коду сервера следующие строчки:
И узнал много интересного:
Host: Debian2
Адрес: localhost
Адрес: 112.221.4.8
Откуда такой ip !?!?
Я правильно понимаю, что мой сервер инициализируется исключительно для локального пользования ... как тогда сделать так чтобы он был доступен из вне? Я в непонятках.
Код: Выделить всё
for(aip = ailist; aip != NULL; aip = aip->ai_next)
{
printf("Адрес: %s\n", aip->ai_canonname);
char address[256];
inet_ntop(AF_INET, &aip->ai_addr, address, 256);
printf("Адрес: %s\n", address);
Net_Socket_FD = Net_Initialize(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN);
}И узнал много интересного:
Host: Debian2
Адрес: localhost
Адрес: 112.221.4.8
Откуда такой ip !?!?
Я правильно понимаю, что мой сервер инициализируется исключительно для локального пользования ... как тогда сделать так чтобы он был доступен из вне? Я в непонятках.
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Сокеты и адресация
Уточните, что там про VMware поминалось выше. Что у вас настроено и как... и какой айпи вы ожидали увидеть...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Имеется виндовая машина, на ней установлена VMWare на которой соответственно одновременно запущено две виртуальные машины с операционкой Debian. VMWare настроена на прозрачную сеть. IP в Debian назначены 192.168.1.143 серверу и 192.168.1.144 клиенту. Соответственно с одной машины пингуются именно по этим ай-пи. Первый из них я и ожидал увидеть. Обе машины видны в сети и видят друг друга.
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Связь установлена!
Решением стала одна строчка:
Помогите осознать произошедшее!
В данном случае я явно прописал IP виртуальной машины. Но откуда вообще взялся IP 112.221.4.8 ???
В файле /ect/hosts записано следующее:
Как сделать так, чтобы сервер самостоятельно выбирал правильный IP для своей инициализации!?
Дело в том что таких серверов должно быть достаточно много и хотелось бы чтобы они хотябы в чем-то самоконфигурировались.
прописывать в настройках каждый чих совсем не хочется.
И еще вопрос ... почему всетаки IP задаваемый изначально отличается от IP выдаваемого функцией inet_ntop???
Сейчас коннект происходит, но inet_ntop выдает IP 152.214.4.8
Не могу непонимать что и почему
.
Если ткнете в статейку подробно объясняющую происходящее буду очень признателен (желательно на Русском.
(не сердчайте други на меня, что сам не открою книжку ... я сейчас читаю огромное кол-во книг и статей, но всего охватить просто не могу, на поиски различных материалов трачу много времени. Коли знаете путевую стейку или ресурс поделитесь)
Решением стала одна строчка:
Код: Выделить всё
if(gethostname(host, MaxHostLen)<0)
{
gLog->_Category_Net->fatal("Ошибка вызова функции gethostname");
exit(1);
}
// ВОТ ЭТУ СТРОЧКУ Я ДОБАВИЛ
strcpy(host, "192.168.1.143");
printf("Host: %s\n", host);Помогите осознать произошедшее!
В данном случае я явно прописал IP виртуальной машины. Но откуда вообще взялся IP 112.221.4.8 ???
В файле /ect/hosts записано следующее:
Код: Выделить всё
127.0.0.1 localhost Debian2
191.168.1.143 Debian2.domen Debian2
..
..Как сделать так, чтобы сервер самостоятельно выбирал правильный IP для своей инициализации!?
Дело в том что таких серверов должно быть достаточно много и хотелось бы чтобы они хотябы в чем-то самоконфигурировались.
прописывать в настройках каждый чих совсем не хочется.
И еще вопрос ... почему всетаки IP задаваемый изначально отличается от IP выдаваемого функцией inet_ntop???
Сейчас коннект происходит, но inet_ntop выдает IP 152.214.4.8
Не могу непонимать что и почему
Если ткнете в статейку подробно объясняющую происходящее буду очень признателен (желательно на Русском.
(не сердчайте други на меня, что сам не открою книжку ... я сейчас читаю огромное кол-во книг и статей, но всего охватить просто не могу, на поиски различных материалов трачу много времени. Коли знаете путевую стейку или ресурс поделитесь)
-
Tanatos
- Сообщения: 45
Re: Сокеты и адресация
Ничего не понимаю
.
Только что все работало, сейчас неработает.
Непонимаю от чего пересборка и повторный запуск серверного приложения приводит к изменению его доступности.
Сейчас буду писать маленькие тесты просто с нуля выкидывая абсолютно все лишнее ....
Только что все работало, сейчас неработает.
Непонимаю от чего пересборка и повторный запуск серверного приложения приводит к изменению его доступности.
Сейчас буду писать маленькие тесты просто с нуля выкидывая абсолютно все лишнее ....
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: Сокеты и адресация
Натолкнулся на эту тему. Проблема оказалась знакомой, поэтому хочу поделиться своим опытом.
Пытался разобраться с приведёным выше примером, но не смог
. Видимо, там используюся функции, до которых я ещё не
Книгу Ричарда Стивенса "UNIX Проффесиональное Программирование" я пока не видел, но как-то (уже довольно давно) натолкнулся на книгу
Системное программирование в UNIX. Руководство программиста по разработке ПО. Авторы -- Кейт Хэвиленд, Дайна Грэй, Бен Салама.
В частности, есть в ней и пример серверного приложения. Я на его основе сделал несколько программ, и все они вполне нормально работали.
(Есть там и аналогичный пример с использованием UDP)
В качестве сервера, обслуживающего запросы по TCP в этой книге приведён следующий
Эта программа просто возвращает принятый знак в верхнем регистре.
В качестве обработчика вместо c=toupper© может быть любой код.
Программа работает нормально, но, на мой взгляд, в ней есть несколько некорректностей.
1. В строке struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY}; указан порт, похожий на 7000.
Но на самом деле это будет 7000 только на процессорах типа с ариметикой BIG-ENDIAN. На интеловских это будет порт 22555.
Есть функция, которая преобразует порт в правильный, но я её имя не могу запомнить. Поэтому написал свой маркос:
#define SwaB(W) ((((W)&255)<<8)|(((W)>>8)&255))
А в Delphi просто использую функцию Swap
2. В начале зачем-то устанавливается обработка сигнала SIGPIPE. Зачем -- не знаю. Но предполагаю, что надо вместо него перехватывать сигнал SIGCHLD.
А в функцию capture поместить
int wst;
wait(&wst);
Без этого после завершения обработки останется зомби.
Впрочем, если fork при образовании нового соединения не выдаётся, это не нужно. Но тогда сервер не сможет одновременно обслуживать несколько клиентов.
Пытался разобраться с приведёным выше примером, но не смог
Книгу Ричарда Стивенса "UNIX Проффесиональное Программирование" я пока не видел, но как-то (уже довольно давно) натолкнулся на книгу
Системное программирование в UNIX. Руководство программиста по разработке ПО. Авторы -- Кейт Хэвиленд, Дайна Грэй, Бен Салама.
В частности, есть в ней и пример серверного приложения. Я на его основе сделал несколько программ, и все они вполне нормально работали.
(Есть там и аналогичный пример с использованием UDP)
В качестве сервера, обслуживающего запросы по TCP в этой книге приведён следующий
Код: Выделить всё
/* Серверный процесс */
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#define SIZE sizeof(struct sockaddr_in)
void catcher(int sig);
int newsockfd;
main{) {
int sockfd;
char c;
struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY};
static struct sigaction act;
act.sa_handler = catcher;
sigfillset(&(act.sa_mask));
sigaction(SIGPIPE, &act, NULL);
/* Создает сокет */
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Ошибка вызова socket");
exit(1);
}
/* Связывает адрес с советом */
if(bind(sockfd, (struct sockaddr *)&server, SIZE) == -1) {
perror("Ошибка вызова bind");
exit(1);
}
/* Включает прием соединений */
if(listen(sockfd, 5) == -1) {
perror("Ошибка вызова listen");
exit(1);
}
for(;;) {
/* Принимает запрос на соединение */
if((newsockfd = accept(sockfd, NULL, NULL)) == -1) {
perror("Ошибка вызова accept");
continue;
}
/* Создает дочерний процесс для работы с соединением */
if(fork()==0) {
while(recv(newsockfd, &c, 1, 0) > 0) {
с = toupper(c);
send(newsockfd, &c, 1, 0);
}
/* После того, как клиент прекратит передачу данных,
сокет может быть закрыт и дочерний процесс
завершает работу */
close(newsockfd);
exit(0);
}
/* В родительском процессе newsockfd не нужен */
close(newsockfd);
}
}
void catcher(int sig) {
close(newsockfd);
exit(0);
}Эта программа просто возвращает принятый знак в верхнем регистре.
В качестве обработчика вместо c=toupper© может быть любой код.
Программа работает нормально, но, на мой взгляд, в ней есть несколько некорректностей.
1. В строке struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY}; указан порт, похожий на 7000.
Но на самом деле это будет 7000 только на процессорах типа с ариметикой BIG-ENDIAN. На интеловских это будет порт 22555.
Есть функция, которая преобразует порт в правильный, но я её имя не могу запомнить. Поэтому написал свой маркос:
#define SwaB(W) ((((W)&255)<<8)|(((W)>>8)&255))
А в Delphi просто использую функцию Swap
2. В начале зачем-то устанавливается обработка сигнала SIGPIPE. Зачем -- не знаю. Но предполагаю, что надо вместо него перехватывать сигнал SIGCHLD.
А в функцию capture поместить
int wst;
wait(&wst);
Без этого после завершения обработки останется зомби.
Впрочем, если fork при образовании нового соединения не выдаётся, это не нужно. Но тогда сервер не сможет одновременно обслуживать несколько клиентов.
-
Rootlexx
- Бывший модератор
- Сообщения: 4471
- Статус: GNU generation
- ОС: Debian GNU/Linux
Re: Сокеты и адресация
MiK13 писал(а): ↑09.05.2008 05:01В строке struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY}; указан порт, похожий на 7000.
Но на самом деле это будет 7000 только на процессорах типа с ариметикой BIG-ENDIAN. На интеловских это будет порт 22555.
Есть функция, которая преобразует порт в правильный, но я её имя не могу запомнить.
Эта функция называется htons.
Этот сигнал посылается процессу при попытке считать/записать данные через нерабочее соединение.
Функцию wait можно использовать без всяких перехватов SIGCHLD.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: Сокеты и адресация
Спасибо. Постараюсь запомнить. Только бы понять, что означают в имени этой функции её составляющие буквы...
А как именно? Судя по имени она будет приостанавливать выполнение процесса до получения сигнала о завершении дочернего процесса.
Поэтому я не предсталяю, как её можно использовать не в обработчике. Если, конечно, не нужно подождать окончания чайлда как в функции system.
-
Rootlexx
- Бывший модератор
- Сообщения: 4471
- Статус: GNU generation
- ОС: Debian GNU/Linux
Re: Сокеты и адресация
uint16_t htons(uint16_t hostshort);
Вообще, есть семейство функций hton? и ntoh?.
Название составляется из этой фразы: host-to-network (или network-to-host) — эти функции конвертируют числа из локального порядка байт в универсальный сетевой порядок и обратно. Буква s в конце названия функции означает, что в качестве аргумента она принимает локальный тип short.
Посмотрите man byteorder.
MiK13 писал(а): ↑10.05.2008 00:54А как именно? Судя по имени она будет приостанавливать выполнение процесса до получения сигнала о завершении дочернего процесса.
Поэтому я не предсталяю, как её можно использовать не в обработчике. Если, конечно, не нужно подождать окончания чайлда как в функции system.
Простое написание обработчика для SIGCHLD и вызов wait в нём при определённых условиях не спасёт от появления зомби. Дело в том, что SIGCHLD не является сигналом реального времени. Если во время исполнения обработчика SIGCHLD придёт ещё некоторое количество SIGCHLD, то по окончании обработки текущего будет доставлен лишь один из пришедших. Так как неизвестно, когда завершится отдельно взятый дочерний процесс, то такую ситуацию нельзя исключать. В принципе, появление процессов-зомби не страшно. После завершения родительского процесса дочерние передаются init, который время от времени подчищает эти процессы. Да и сам процесс-зомби — это лишь запись в таблице процессов о его PID, использованных ресурсах и коде завершения. Никаких ресурсов процесс-зомби не занимает. Но если хочется избежать их появления, то можно поступить следующим образом: в, скажем, списке запоминаете все PID дочерних процессов и после создания очередного проходитесь по этому списку, вызывая для каждого waitpid с флагом WNOHANG, что приведёт к простому возврату при отсутствии завершённых дочерних процессов. Таким образом время от времени будет происходить очистка процессов-зомби (при каждом новом соединении). Можно же написать соответствующую функцию периодической очистки и запустить её в начале выполнения программы в отдельном потоке. Правда, некоторое время назад это было невозможно (то, что дочерние процессы должны быть дочерними и для всех потоков родительского процесса, записано в POSIX Threads, но реализация Linux этого не включала). Как сейчас — не знаю. В любом случае есть первый вариант.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: Сокеты и адресация
Rootlexx, спасибо за разъяснение. Про функцию теперь. надеюсь, запомню. Я встречал эти функции в .h-файле, видел, что они есть и для 2-байтовых и для 4-байтовых параметров. Но, т.е. смысл букв был мне не ясен. Поэтому и не запомнил их.
По поводу чистки от зомби... пока для меня это не актуально -- пока не приходится писать сложные системы, состоящие из многих дочерних процессов, предпочитаю из раздельный запуск с обменом через общую область памяти.
По поводу чистки от зомби... пока для меня это не актуально -- пока не приходится писать сложные системы, состоящие из многих дочерних процессов, предпочитаю из раздельный запуск с обменом через общую область памяти.