На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие друзья! Поздравляем вас с днём Победы!
msm.ru
  
    > Проблемы при передаче буфера данных между клиентом и сервером , Операционная система - MCBC, среда разработки - Kylix 3.0
      Доброго времени суток!
      Столкнулся с такой проблемой,
      Есть клиент на основе компонента TcpClient и сервер, который работает на АПИ.
      При передаче клиентом буфера, после непосредственной отправки данных, клиент ждет ответа и засыпает. Как я понял, срабатывает так называемый блокирующий сокет. Просыпается только тогда, когда приходит ответ от сервера.
      С сервером та же история. Тоже форма блокируется, даже при использовании нити, которая занимается непосредственно чтением.
      Подскажите, как сделать, чтобы форма не блокировалась? И правильно ли я общаюсь клиентом и сервером.
      П.с. Клиент возможно переписать на АПИ, но не желательно.

      Клиент хидер
      ExpandedWrap disabled
        //---------------------------------------------------------------------------
        #ifndef DTCPClientH
        #define DTCPClientH
         
        #include <clx.h>
         
        #include <Sockets.hpp>          // для ТСП клиента
         
        #include "DIPAddress.h"
        #include "DThreadUKV.h"
         
        class DTCPClient
        {
        public:
                DTCPClient(DIPAddress *_IP, AnsiString Port);   // конструктор
                ~DTCPClient();
         
                void __fastcall connect();                         // Создать подключение к серверу
                void __fastcall disconnect();                      // Разрыв связи с сервером
         
                void __fastcall SendBuf(unsigned char *_buf, int _size);            // Отправить серверу буфер
         
                // События для компонента
                void __fastcall _OnConnect(TObject *Sender);
                void __fastcall _OnDisconnect(TObject *Sender);
                void __fastcall _OnError(TObject *Sender, int SocketError);
                void __fastcall _OnReceive(TObject *Sender, PChar Buf_recv, int &DataLen_recv);
         
                // Указатели на функцию
                void __fastcall (__closure *OnConnect)();
                void __fastcall (__closure *OnDisconnect)();
                void __fastcall (__closure *OnError)(int SocketError);
                void __fastcall (__closure *OnReceive)(PChar Buf_recv, int &DataLen_recv);
         
                void __fastcall ThreadReceive ();
         
         
        private:
               TTcpClient *TcpClient;                   // Объект ТСП клиента
               bool connection;
               DThreadUKV *Thread;
         
        };
        //---------------------------------------------------------------------------
        #endif


      Клиент
      ExpandedWrap disabled
        //---------------------------------------------------------------------------
        #pragma hdrstop
        #include "DTCPClient.h"
         
        char _buf[1024];
        //---------------------------------------------------------------------------
        //Конструктор
        DTCPClient::DTCPClient(DIPAddress *_IP, AnsiString Port)
        {
                TcpClient = new TTcpClient(NULL);
         
                OnConnect = NULL;
                OnDisconnect = NULL;
                OnError = NULL;
         
                AnsiString host;
                host.printf( "%s", _IP->getAddressStringFULL() );
         
                TcpClient->RemoteHost = host;
                TcpClient->RemotePort = Port;
         
                TcpClient->OnConnect = _OnConnect;
                TcpClient->OnDisconnect = _OnDisconnect;
                TcpClient->OnError = _OnError;
                TcpClient->OnReceive = _OnReceive;
         
                connection = false;
         
                Thread = new DThreadUKV( true, &ThreadReceive );
         
        }
        //---------------------------------------------------------------------------
        //Деструктор
        DTCPClient::~DTCPClient()
        {
                Thread->Terminate();
                if(connection)
                {
                        disconnect();
                        delete TcpClient;
                }
        }
         
        //---------------------------------------------------------------------------
        //Создать соединение
         
        void __fastcall DTCPClient::connect()
        {
                // Если не подключено, то подключить
                if(!TcpClient->Connected)
                {
                        try
                        {
                                TcpClient->Connect();
                                connection = true;
         
                        }
                        catch(...)
                        {
                        }
                }
        }
         
        //--------------------------------------------------------------------------
        // Разрыв связи с сервером
        void __fastcall DTCPClient::disconnect()
        {
                TcpClient->Disconnect();
        }
         
        //--------------------------------------------------------------------------
        // Событие подключения
        void __fastcall DTCPClient::_OnConnect(TObject *Sender)
        {
                if ( (OnConnect) != NULL)
                        (OnConnect)();
        }
         
        //--------------------------------------------------------------------------
        // Событие отключения
        void __fastcall DTCPClient::_OnDisconnect(TObject *Sender)
        {
                if ( (OnDisconnect) != NULL)
                        (OnDisconnect)();
        }
         
        //--------------------------------------------------------------------------
        // Событие ошибки
        void __fastcall DTCPClient::_OnError(TObject *Sender, int SocketError)
        {
                if ( (OnError) != NULL)
                        (OnError)(SocketError);
        }
         
        //--------------------------------------------------------------------------
        // Событие приема данных
        void __fastcall DTCPClient::_OnReceive(TObject *Sender, PChar Buf_recv, int &DataLen_recv)
        {
                Thread->Suspend();
                if ( (OnReceive) != NULL )
                        (OnReceive)(Buf_recv, DataLen_recv);
        }
         
        //---------------------------------------------------------------------------
        // Метод отправки буфера
        void __fastcall DTCPClient::SendBuf(unsigned char *_buf, int _size)
        {
                TcpClient->SendBuf(_buf, _size, 0);
                Thread->Resume();
        }
         
        //---------------------------------------------------------------------------
         
        void __fastcall DTCPClient::ThreadReceive ()
        {
          TcpClient->ReceiveBuf(_buf, 1024, MSG_DONTWAIT);
        }
         
        //---------------------------------------------------------------------------
         
        #pragma package(smart_init)


      Сервер хидер
      ExpandedWrap disabled
        //---------------------------------------------------------------------------
         
        #ifndef DUKVSocketUnitH
        #define DUKVSocketUnitH
         
        #include "DUKVServerUnit.h"
        #include "DUKVThreadUnit.h"
         
        #include <clx.h>
         
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <stdio.h>
        #include <fcntl.h>
         
        class DSocket
        {
           public:
              DSocket();
              ~DSocket();
         
              void __fastcall _Read ();
         
           private:
              int sock, listener;
              struct sockaddr_in addr_in;
              char buf[1024];
              int bytes_read;
              bool flag;
              DUKVThread *pThreadUKV;
        };
         
        //---------------------------------------------------------------------------
        #endif


      Сервер
      ExpandedWrap disabled
        //---------------------------------------------------------------------------
         
        #pragma hdrstop
        #include "DUKVSocketUnit.h"
         
         
        //---------------------------------------------------------------------------
        /**
          \fn           DSocket::DSocket()    
          \brief        Конструктор класса    
        */
        DSocket::DSocket()
        {
            OnRecData = NULL;
            flag = false;
         
            listener = socket(AF_INET, SOCK_STREAM, 0);
         
            if(listener < 0)
            {
                perror("socket");
                exit(1);
            }
         
            addr_in.sin_family = AF_INET;
            addr_in.sin_port = htons(6800);
            addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
            if(bind(listener, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0)
            {
                perror("bind");
                exit(2);
            }
         
            pThreadUKV = new DUKVThread( true, &_Read ); // ... для нити
         
            pThreadUKV->Resume(); //возобнавление работы нити
        };
         
        //---------------------------------------------------------------------------
        /**
          \fn           DSocket::~DSocket()
          \brief        Деструктор класса
        */
        DSocket::~DSocket()
        {
         
        };
        //---------------------------------------------------------------------------
        /**
          \fn           void __fastcall DSocket::_Read ()
          \brief        Опрос буфера
        */
        void __fastcall DSocket::_Read ()
        {
           //memset(buf, 0, 2048);        //обнуление приемного буфера
           //bytes_read = recv(sock_in, buf, 2048, MSG_DONTWAIT);// опрос сокета
         
                listen(listener, 1);
         
                if (flag == false)
                {
                        sock = accept(listener, NULL, NULL);
         
                        if(sock < 0)
                        {
                                perror("accept");
                                exit(3);
                        }
         
                        flag = true;
                 }
                        bytes_read = recv(sock, buf, 1024, 0);
                        if(bytes_read <= 0)
                                flag = false;
         
                        send(sock, buf, bytes_read, 0);   //ответить тем же
        };
         
        //---------------------------------------------------------------------------
        #pragma package(smart_init)
        Цитата digital @
        ...При передаче клиентом буфера, после непосредственной отправки данных, клиент ждет ответа и засыпает. Как я понял, срабатывает так называемый блокирующий сокет. Просыпается только тогда, когда приходит ответ от сервера.
        С сервером та же история. Тоже форма блокируется, даже при использовании нити, которая занимается непосредственно чтением....

        постараюсь не разводить флейм. если коротко - код НЕ рабочий. копать в сторону юзанья TCP слоя. А именно - ну НЕТ там дайтаграм - НЕТУ. А Вы делаете вывод, что то что уйдёт то и прийдёт в виде кванта - одно из частых заблуждений. В программе хэллоу ворд - покатит. под ударными нагрузками - загнётся, возможно плавающая бага.

        по поводу блокировки уровня который вызывает сие.
        Да, надо организовывать отдельный поток (по уму), но это не обязательно. Если Вы аккуратно разрулите очередь оконных(самой программы) сообщений - то всё у вас задышит. разгребать нуна в момент простоя TCP соединения.

        Т.е. типа запрос с флагом на приёме - дабы узнать длину пришедшего буфера. Если не ноль - принимаем (с учётом вышесказанного!). Если нуль - тестим очередь сообщений у программы. Есть сообщение - ставим его на обработку. Это грубо.


        удачи Вам
        (круглый)
          kolobok0, о каких сообщениях речь?
            Цитата Adil @
            о каких сообщениях речь?

            см. MSDN, WinAPI и т.д..

            удачи Вам
            (круглый)
              Цитата kolobok0 @
              см. MSDN, WinAPI и т.д..
              см.
              Цитата digital @
              Операционная система - MCBC, среда разработки - Kylix 3.0
              :)
                Цитата Adil @
                ..Операционная система - MCBC, среда разработки - Kylix 3.0..

                затупил. приношу свои извенения.
                  ThreadReceive вызывается из Thread, который вызывает ReceiveBuf, первая строчка которого Thread->Suspend();
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0449 ]   [ 16 queries used ]   [ Generated: 10.05.24, 13:35 GMT ]