>А вот по части recv, проблема в сигнале. Ведь сигналом прерывается выполнение
>программы, обрабатывается прерывание и управление возвращается обратно в ту же точку
>программы. Почему же должна прерываться операция считывания/ожидания данных из сокета?
Уж не помню, почему, но системные вызовы ввода/вывода (типа read/write/recv/send/etc) точно ведут себя именно так. То есть могут вернуть меньше, чем запрошено, если успели что-то получить (в случае с read/recv) или -1 с ошибкой Interrupted system call - если ничего не успели получить к моменту прихода сигнала. Это относится к варианту по-умолчанию. Разумеется их поведение зависит от настроек дескриптора (сокета). Например в блокирующем и неблокирующем режиме оно совершенно разное. Всё это описано в соответствующих манах.
>По части кода:
>Код реконнекта:
>
>на самом деле коннект происходит так:
>main()
>{
>reconnect:
> do
> {
> // реконнект
> if(-1==c.connect())
> {
> printf("Не могу присоединиться к серверу");
> sleep(flags.timeout_reconnect*60);
> }
> else
> {
> er=(char*)malloc(255);
> printf("Успешно присоединились к серверу");
> break;
> }
> }while(!flags.flag_off);
> // далее читаем данные:
> while(!flags.flag_off)
> {
> t=c.read((char*)&m,sizeof(m));
> if(t==-1)
> {
> // ошибка
> goto reconnect;
использовать goto, тем более в C++ - мало какая идея может быть хуже...
> }
> и т.д. из предыдущего листинга
>
>По части класса клиента сокетов:
>
>int client_tcp::connect(void)
>{
> // прописываем порт и адрес
>#ifdef _WIN32
> if(SOCKET_ERROR==::connect(s,(const struct sockaddr *)&ad,sizeof(ad)))
>#else
> if(-1==::connect(s,(const struct sockaddr *)&ad,sizeof(ad)))
>#endif
> {
> set_error("connect",errno);
> return -1;
> }
> return 0;
>}
>// чтение:
>int client_tcp::read(char* buf, int len)
>{
> int t=len;
> while(t)
> {
> int m=recv(s,buf,t,0);
>#ifdef _WIN32
> if(m==SOCKET_ERROR)
>#else
> if(m==-1)
>#endif
> {
вот здесь нужно вставить дополнительную проверку на EINTR
> set_error("recv",errno);
> return -1;
> }
> if(m==0)
> {
> set_error("'recv' т.к.клиент отсоединился.",errno);
> return 0;
> }
> if(!m)return len-t;
Это никогда не выполнится, так как при m==0 выйдет двумя строками раньше
Конечно, вероятно строка осталась от какого-то предыдущего варианта и в данном случае ничего страшного не представляет, но она позволяет предположить, что где-то ещё есть какие-то подобные "хвосты", от которых может уже что-то зависеть
> t-=m;
> buf+=m;
> }
> return len;
>}
Вообще, если данные нужны именно все, имеет смысл сделать, чтобы этот метод возвращал bool - либо всё получил, либо что-то произошло (типа разрыва соединения)
Касательно метода connect() - нужно проследить, где и что ещё делается с сокетом. Возможно он всё-таки где-то закрывается или просто полю s присваивается что-нибудь не то.
>Насчёт обработчика сигнала. Мне нужно избавиться от зомби, чтобы родительский процесс, вызвав
>kill(SIGUSR1,pid_дитя) понял, что дитя завершило работу и можно освобождать соответствующие данные.
>Иначе, если дитя стало зомби (жуть какая ;-) ), вызов kill()
>для дитя не завершается с ошибкой и родительский думает что дитя
>всё ещё работает. Поэтому обработчик нужен.
Как я уже говорил (два раза), чтобы не было зомби, можно просто поставить в качестве обработчика сигнала SIGCHLD специальное значение SIG_IGN. Хотя это работает не на всех платформах. Короче man signal(2). Но коль скоро всё-таки нужно определять, что дочерний процесс завершился, логично было бы выставлять в имеющемся обработчике какой-нибудь флаг, информирующий об этом, вместо того, чтобы слать какие-то сигналы несуществующему процессу.
Кстати fork может вернуть кроме 0 и pid дочернего процесса ещё и -1.
P.S. Без обид, но мне кажется, если это всё нормально заработает - это будет чудо.