Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.59.80.187] |
|
Сообщ.
#1
,
|
|
|
Доброго времени суток!
Столкнулся с такой проблемой, Есть клиент на основе компонента TcpClient и сервер, который работает на АПИ. При передаче клиентом буфера, после непосредственной отправки данных, клиент ждет ответа и засыпает. Как я понял, срабатывает так называемый блокирующий сокет. Просыпается только тогда, когда приходит ответ от сервера. С сервером та же история. Тоже форма блокируется, даже при использовании нити, которая занимается непосредственно чтением. Подскажите, как сделать, чтобы форма не блокировалась? И правильно ли я общаюсь клиентом и сервером. П.с. Клиент возможно переписать на АПИ, но не желательно. Клиент хидер //--------------------------------------------------------------------------- #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 Клиент //--------------------------------------------------------------------------- #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) Сервер хидер //--------------------------------------------------------------------------- #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 Сервер //--------------------------------------------------------------------------- #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) |
Сообщ.
#2
,
|
|
|
Цитата digital @ ...При передаче клиентом буфера, после непосредственной отправки данных, клиент ждет ответа и засыпает. Как я понял, срабатывает так называемый блокирующий сокет. Просыпается только тогда, когда приходит ответ от сервера. С сервером та же история. Тоже форма блокируется, даже при использовании нити, которая занимается непосредственно чтением.... постараюсь не разводить флейм. если коротко - код НЕ рабочий. копать в сторону юзанья TCP слоя. А именно - ну НЕТ там дайтаграм - НЕТУ. А Вы делаете вывод, что то что уйдёт то и прийдёт в виде кванта - одно из частых заблуждений. В программе хэллоу ворд - покатит. под ударными нагрузками - загнётся, возможно плавающая бага. по поводу блокировки уровня который вызывает сие. Да, надо организовывать отдельный поток (по уму), но это не обязательно. Если Вы аккуратно разрулите очередь оконных(самой программы) сообщений - то всё у вас задышит. разгребать нуна в момент простоя TCP соединения. Т.е. типа запрос с флагом на приёме - дабы узнать длину пришедшего буфера. Если не ноль - принимаем (с учётом вышесказанного!). Если нуль - тестим очередь сообщений у программы. Есть сообщение - ставим его на обработку. Это грубо. удачи Вам (круглый) |
Сообщ.
#3
,
|
|
|
kolobok0, о каких сообщениях речь?
|
Сообщ.
#4
,
|
|
|
Цитата Adil @ о каких сообщениях речь? см. MSDN, WinAPI и т.д.. удачи Вам (круглый) |
Сообщ.
#5
,
|
|
|
Цитата kolobok0 @ см.см. MSDN, WinAPI и т.д.. Цитата digital @ Операционная система - MCBC, среда разработки - Kylix 3.0 |
Сообщ.
#6
,
|
|
|
Цитата Adil @ ..Операционная система - MCBC, среда разработки - Kylix 3.0.. затупил. приношу свои извенения. |
Сообщ.
#7
,
|
|
|
ThreadReceive вызывается из Thread, который вызывает ReceiveBuf, первая строчка которого Thread->Suspend();
|