Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Странное взаимное поведение сокета и обработчика событий от клавиатуры  (Прочитано 628 раз)
0 Пользователей и 1 Гость смотрят эту тему.
demon051
Постоялец

ru
Offline Offline

« : 02-04-2018 13:43 » 

Всем привет.

пытаюсь сделать аналог kbhit. надо в целях тестирования программы.
ну естественно подсмотрел на форумах варианты.
например

Код:

int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  printf("!!! wait KBHIT !!!\n"); //вывожу для отладки

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  printf("!!! ch = %d !!!\n", ch);//вывожу для отладки

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    printf("!!! KBHIT Catch !!!\n"); //вывожу для отладки
    return 1;
  }

  return 0;
}




всё бы ничего.
и работает как бы...

В дочернем потоке вертится прослушка сокета. клиент подключается шлёт что=то, сервер это что-то обрабатывает.
если в процессе нажать на клавишу, то kbhit срабатывает.
но если клиент отключился от сервера и при этом закрыть прослушиваемый сокет, то kbhit работать перестает!
т.е. не принимает ввод с клавиатуры.

как побороть даже не догадываюсь...

Код:

int main(int argc, char *argv[])
{

    BaseModuleManager bmm(1024, "/usr/bin/bm-database");
    bmm.loadConfigurationFromDB();
    bmm.startServer(); //тут запускается поток с ожиданием подключения клиентаи дальнейшим обменом

    sleep(1);
    while (!kbhit())
    {
        sleep(1);
    }

    bmm.stopServer();

    return 0;
}

сокет при отключении клиента закрывается так

Код:
close(sd);            
 shutdown(sd, SHUT_RDWR);
 sd=0;

после этого клиент, если ему надо, нормально переподключается к серверу, данные от него приходят,НО!!!! КЛАВИАТУРА на ввод НЕ РЕАГИРУЕТ!!!
 printf("!!! ch = %d !!!\n", ch);  всё время печатает "-1"

как говорится, хелп ми, сос ми Улыбаюсь
я в трансе Улыбаюсь

OS Debian, TCP, неблокирующие сокеты.

заранее спасибо.

UPD
вставил perror в цикле kbhit
так вот после закрытия сокета начинает выводить: bad file descriptor

Это чо за на....
« Последнее редактирование: 02-04-2018 13:54 от demon051 » Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #1 : 02-04-2018 14:06 » 

Похоже Вы первый раз закрыли сокет, а второй раз закрыли stdin, который, как известно, имеет значение равное 0. Неправильное решение проблемы - поменять sd=0; на sd=-1; Правильное - найти - почему Вы выполняете закрытие сокета два раза.
Записан
demon051
Постоялец

ru
Offline Offline

« Ответ #2 : 02-04-2018 14:21 » 

Похоже Вы первый раз закрыли сокет, а второй раз закрыли stdin, который, как известно, имеет значение равное 0. Неправильное решение проблемы - поменять sd=0; на sd=-1; Правильное - найти - почему Вы выполняете закрытие сокета два раза.

да точно!
спасибо! нашел!

и тогда ещё вопрос.
какова правильная последовательность вызовов при закрытии сокета: сначала клозе потом шутдаун  или наоборот?
или нет разницы.
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #3 : 02-04-2018 14:26 » 

можно обойтись одним close(sd); shutdown() нужно для реализаций разных закрытий наполовину, таким образом можно сообщить, что больше Вы не намерены передавать данные, но ожидаете приём, или наоборот.
Записан
demon051
Постоялец

ru
Offline Offline

« Ответ #4 : 02-04-2018 14:33 » 

можно обойтись одним close(sd);

Вот тут пока что не обходится ни тем ни другим Жаль
ни обоими вместе.
в случае когда клиента отключают со стороны сервера при его (сервера) завершении, возникает ситуация, что после перезапуска сервера не получается запустить прослушку подключений клиентов

bind(listener, (struct sockaddr *)&addr, sizeof(addr))
возвращает ошибку  Address already in use

пытаюсь закрыть листенер этими операциями - не помогает.
возможно нужно отвязать его ? как - через bind или есть иная функция?



Записан
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 02-04-2018 14:43 » 

Как вариант использовать метод setsockopt(), для установки опции SO_REUSEADDR
а вообще - вот ОЧЕНЬ КРАТКОЕ изложение по теме
https://habrahabr.ru/post/173415/
полезно почитать, чтобы не гадать почему и какую функцию применить Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
demon051
Постоялец

ru
Offline Offline

« Ответ #6 : 03-04-2018 04:56 » 

Как вариант использовать метод setsockopt(), для установки опции SO_REUSEADDR
а вообще - вот ОЧЕНЬ КРАТКОЕ изложение по теме
https://habrahabr.ru/post/173415/
полезно почитать, чтобы не гадать почему и какую функцию применить Улыбаюсь

сыпасиба! Улыбаюсь

 setsockopt() выручил.

я правильно понимаю, что close - штатное закрытие сокета. а шутдаун - типа экстренное?
в статье про это ничего.
в сети - кто в лес кто по дрова. а кто - всё сразу Улыбаюсь
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #7 : 03-04-2018 05:43 » 

я правильно понимаю, что close - штатное закрытие сокета. а шутдаун - типа экстренное?
нет
В man shutdown() пишут, что для возможности закрытия всего или части полнодуплексного соединения. Вот вариант на русском.
Записан
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 03-04-2018 07:25 » 

Похвальное стремление разобраться Улыбаюсь
Но, создается такое впечатление, что Вы пытаетесь написать программу, до конца не представляя себе механизмы сокетов и протоколов связи.
Рекомендую книгу: Йон Снейдер "Эффективное программирование TCP/IP". В сети она точно есть, сам скачивал - поищите. Настоятельно рекомендую. Более разжеванного материала с примерами рабочего кода, причем и для *nix и для винды, я, пожалуй, не видел. Книга, кстати, не очень толстая.
Поверьте моему опыту - лучше потратить какое-то время на внимательное прочтение книги, хотя бы начало, чем пытаться освоить программирование TCP методом "программного тыка" и работа пойдет намного быстрее, а главное - будет явно более осмысленной. Судя по Вашим вопросам, у Вас пока нет общей картины того, как работать с с сокетами и протоколом. Почитайте Снайдера, отпадет сразу куча вопросов, отвечать на Ваши вопросы ведь нисколько не жалко, только времени у Вас на такое познание уйдет на порядок больше ...
« Последнее редактирование: 03-04-2018 07:31 от Михалыч » Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
demon051
Постоялец

ru
Offline Offline

« Ответ #9 : 04-04-2018 12:11 » new

Похвальное стремление разобраться Улыбаюсь
Но, создается такое впечатление, что Вы пытаетесь написать программу, до конца не представляя себе механизмы сокетов и протоколов связи.
Рекомендую книгу: Йон Снейдер "Эффективное программирование TCP/IP". В сети она точно есть, сам скачивал - поищите. Настоятельно рекомендую. Более разжеванного материала с примерами рабочего кода, причем и для *nix и для винды, я, пожалуй, не видел. Книга, кстати, не очень толстая.
Поверьте моему опыту - лучше потратить какое-то время на внимательное прочтение книги, хотя бы начало, чем пытаться освоить программирование TCP методом "программного тыка" и работа пойдет намного быстрее, а главное - будет явно более осмысленной. Судя по Вашим вопросам, у Вас пока нет общей картины того, как работать с с сокетами и протоколом. Почитайте Снайдера, отпадет сразу куча вопросов, отвечать на Ваши вопросы ведь нисколько не жалко, только времени у Вас на такое познание уйдет на порядок больше ...

почитаем Улыбаюсь

гляньте, если можно, эту темку https://forum.shelek.ru/index.php/topic,31050.new.html#new
опять попал в непонятное
теперь с датой и временем Улыбаюсь
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines