Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Неблокирующий сервер, Как правильно использовать select 
:(
    Опции темы
Sphinx
Дата 19.1.2007, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Написал стандартную функцию сервера, но она, если нет соединения, останавливается на accept. Мне же нужно периодически проверять состояние одной глобальной переменной. Как я понял подобное можно сделать с помощью select. Но ничего не получается. Дайте простейший пример сервера с использованием select.
PM MAIL   Вверх
Anikmar
Дата 19.1.2007, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Я ничего не понял, если честно...

Что такое стандартная функция сервера?

Нужно периодически просматривать появилось ли соединение?
PM MAIL ICQ   Вверх
Sphinx
Дата 19.1.2007, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Я имел ввиду, что использовал стандартний пример сервера, которые есть во многих учебниках.
А проверять надо состояние переменной совершенно не имеющей отношение к сети. В общем надо чтобы сервер не зависал на accept, а организовать перед ним цикл, в котором делать проверку на появление соединения ну и попутно просматривать эту переменную.
PM MAIL   Вверх
W4FhLF
Дата 19.1.2007, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 1
Всего: 121



Создай функцию с accept в отдельном потоке или используй WSAAccept 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
ptr
Дата 22.1.2007, 07:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Есть много способов: использовать select с установленным timeout, использовать неблокирующие сокеты, использовать многопоточность, или установить таймер. Выбирай любой.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Sphinx
Дата 23.1.2007, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Поясню, более конкретно, чего я хочу. Может будут другие варианты, как это реализовать. Сервер запускается в отдельном потоке, который создает загружаемый плагин. При выгрузке плагина, хочется, чтобы сервер корректно завершал свою работу. В блокирующем режиме сервер вызывает accept и управление к нему не возвращается (пока кто-то не создаст соединение). Была идея перед вызовом accept сделать цыкл в котором с помощью select определять попытку соединения, но ничего не получилось. Потом попробовал использовать неблокирующий сокет. Вот код сервера:
Код

void DoServer()
{
SOCKET lSck,cSck;
SOCKADDR_IN sin;
int nlen;
    if((lSck=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
        Error("ERROR: Failed to create listening socket %d");
        return;
    }
    nlen=1;
    if(ioctlsocket(lSck,FIONBIO,&nlen)==SOCKET_ERROR)AddLog("Error switch in nonblock mode");
    else AddLog("Socket in nonblock mode");
    sin.sin_family=AF_INET;
    sin.sin_port=htons(Port);
    sin.S_addr=INADDR_ANY;
    if(bind(lSck,&sin,sizeof(sockaddr))!=0){
        Error("ERROR: Failed to bind() listening socket %d");
        return;
    }
    if(listen(lSck,5)!=0){
        Error("ERROR: Failed to listen() socket %d");
        return;
    }
    do{
        nlen=sizeof(sockaddr);
        while((cSck=accept(lSck,&sin,&nlen))==-1){
            if(WSAGetLastError()!=10035){
                Error("ERROR - accept() failed %d");
                return;
            }
            Sleep(0);
            if(processtread==FALSE)return;
        }
        nlen=sizeof(sockaddr);
        getpeername(cSck,&sin,&nlen);
        InputMsg(cSck);
        closesocket(cSck);
    }while(processtread);
}

Все отрабатывает как надо, кроме завершения работы - зависает на вызова WSACleanup(). Вот код главного потока:
Код

void MainThread(dword i)
{
WSADATA WSAData;
    runthread=TRUE;
    AddLog("Start Server Thread");
    if(WSAStartup(0x202,#WSAData)!=0)Error("WSAStartup() failed with error code %d");
    else DoServer();
    WSACleanup();
    AddLog("Close Server Thread");
    runthread=FALSE;
}


PM MAIL   Вверх
Enelar
Дата 26.3.2011, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 141
Регистрация: 13.1.2008

Репутация: нет
Всего: 1



Цитата(Sphinx @  23.1.2007,  08:53 Найти цитируемый пост)
Была идея перед вызовом accept сделать цыкл в котором с помощью select определять попытку соединения, но ничего не получилось. 

Что именно у вас не получилось?
Код

readfds:

    * If listen has been called and a connection is pending, accept will succeed.
    * Data is available for reading (includes OOB data if SO_OOBINLINE is enabled).
    * Connection has been closed/reset/terminated.

Собственно на сокете, находящемся в состоянии прослушки, функция оставит его в массиве согласно пункту один - если есть входящее соединение, и следующий вызов функции accept не заблокирует приложение. Есть небольшая особенность с функцией select - она не расчитанна на вызов в массиве, нужно делать хотя бы Sleep(1) а лучше 10.

А вообще для подобных целей есть только 2 норм варианта
1) Слушающий поток, отдельный. Блокируется в функции accept, при ее успехе завершается с кодом - входящий сокет, или 0 если ошибка. В основном потоке проверяется не завершился ли дополнительный. Возможны модификации.
2) Использование неблокирующих сокетов(что по моему личному мнению намного лучше).
PM MAIL   Вверх
Олег2005
Дата 27.3.2011, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11




M
Олег2005
Enelar, внимательно следите за датами опубликования темы и ответов - последний ответ в тему был 4 года назад.....

PM MAIL WWW MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0631 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.