Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вопрос по компоненту - TServerSocket. Как обработать отключение юзера?

1
20 ноября 2005 года
kot_
7.3K / / 20.01.2000
Компонент работает в режиме stThreadBlocking. При коннекте пользователя стартует поток загружающий необходимые ресурсы.
Обрабатывается событие OnGetThread:
 
Код:
SocketThread = new TClientThreadE(true,ClientSocket);
((TClientThreadE *)SocketThread)->Resume();

Соответственно старует поток - как и должно. Функция Execute реализована следующим образом:
 
Код:
while(!Terminated||Client->Connected)
 {
  ;
 }

  delete DataModule;       //

В собитии ssOTCThreadEnd описываю:
 
Код:
((TClientThreadE *)Thread)->Terminate();

В потоке соответственно переопределена Terminate(). Сам поток объявлен как наследник TServerClientThread. Но на сервере поток не завершается. В чем моя ошибка?
2.3K
21 ноября 2005 года
ART-CODE
134 / / 15.11.2004
Я лично так делать даже не пробовал - а зачем так ?

А вот если работать с асинхронными сокетами в разных потоках, то делаем так:
в событии ClientConnect создаем новый поток, переназначаем в него обработку событий сокета...
 
Код:
void __fastcall TPOPForm:: POP3ServerClientConnect(
      TObject *Sender, TCustomWinSocket *Socket)
{
TPOP3Thread * POP3=new TPOP3Thread(true);
POP3->FreeOnTerminate=true;
Socket->onSocketEvent=POP3->OnSocketEvent;
Socket->onErrorEvent=POP3->OnSocketErrorEvent;
POP3->Resume();
Socket->Data=POP3; // пометили сокет указателем на поток, который отвечает за работу с ним.
}

Вот и все, далее вся работа идет в потоке POP3, где и реализованы входные функции для событий сокета - OnSocketEvent и OnSocketErrorEvent
Код:
void __fastcall TPOP3Thread:: OnSocketEvent(TObject *Sender, TCustomWinSocket* Socket, TSocketEvent SocketEvent)
 {
  switch(SocketEvent)
        {
         case seRead:
                {
                POP3Read(Socket);// уходим в обработку чтения данных из сокета
                return;
                }
         case seDisconnect:
                {
                POP3Disconnect(Socket);
                }
// вызов обработки других событий...
        }
 }


P.S.
IMHO - есть сомнения насчет цикла while(!Terminated||Client->Connected)
- наверно он у тебя будет выполняться до тех пор пока оба значения не изменят свой статус на противоположный
замени || на &&.. (но может я ошибаюсь...)


1
21 ноября 2005 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by ART-CODE
Я лично так делать даже не пробовал - а зачем так ?


Спасибо за помощь. А то чегото действительно перемудрил и запутался. В своем варианте я вообще реализовал без потоков в конечном итоге (запарили! :) ). Получилось примерно такая вот байда (обработку ошибок я удалил, что бы не захламлять код) :

Код:
struct sockaddr_in localaddr,
                       clientaddr;
  SOCKET sServerListen;
  SOCKET ClientSockets[MAX_CONNECTION];
  int TotalSocket;
  int  iSize;
  unsigned short port;
  FD_SET ReadSet;
  int ReadySock;
//Включаем сокет
sServerListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

 ULONG ulBlock;
 ulBlock = 1;

    localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(port);
    listen(sServerListen, 4);

Ну а дальше запускаем цикл и ждем гостей. Макс количество подключений задается реестр, файл настройки. Естественно такие вещи удобней загружать в службе а не в программе.
Код:
while (Terminated)
    {
     FD_ZERO(&ReadSet);
     FD_SET(sServerListen, &ReadSet);
    for (int i=0; i<TotalSocket; i++)
          if (ClientSockets != INVALID_SOCKET)
            FD_SET(ClientSockets, &ReadSet);
               if ((ReadySock = select(0, &ReadSet, NULL, NULL, NULL)) == SOCKET_ERROR)
        {       ;
                }
        //Смотрите кто пришел!
          else if (FD_ISSET(sServerListen, &ReadSet))
        {
        iSize = sizeof(clientaddr);
            ClientSockets[TotalSocket] = accept(sServerListen, (struct sockaddr *)&clientaddr,
                            &iSize);
if (ClientSockets[TotalSocket] == INVALID_SOCKET)
                        {
                            break;
                            }
         TotalSocket++;
        }
        //Нам шлют приветы
         for (int i=0; i<TotalSocket; i++)
          {
                      if (ClientSockets == INVALID_SOCKET){
                        TotalSocket--;
                         continue;
                      }
         if (FD_ISSET(ClientSockets, &ReadSet))
         {
             char szRecvBuff[1024];
             char *szSendBuff;
                         int ret = recv(ClientSockets, szRecvBuff, sizeof(szRecvBuff), 0);
                           if (ret == 0)
                            {
                             ClientSockets=INVALID_SOCKET;
                             TotalSocket--;
                  break;
                            }
                          else if (ret == SOCKET_ERROR)
                           {
                             TotalSocket--;
                             break;
                            }
                      AnsiString tmp  = szRecvBuff;
                      //Что то прочитали - проверим:
                      if(tmp1=="Login"){
                       szSendBuff = new char[tmp.Length()+2];
                      strcpy(szSendBuff, "Pass#\n\0");
                      }
            ...
                      ret = send(ClientSockets, szSendBuff, sizeof(szSendBuff), 0);
    }

            }
           }
    closesocket(sServerListen);
    return ;
1
22 ноября 2005 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by ART-CODE


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

Хотя нет в принципе. Вполне можно использовать свойство Data для получения доступа к потоку сокета, поэтому вектор тут нафиг не нужен. С этим разобрался.

И данная схема уперто не хочет почемуто работать как служба - даже интерактивная. Выдает ошибку ассинхронного сокета при подключении пользователя и баста.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог