976
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 16:30
|
QAbstractSocket::LowDelayOption - частично решил проблему, теперь все приходит нормально (хотя конечно проверку я введу, но когда приедет разработчик сервера). теперь непонятная проблема - когда я шлю на сервер запрос, открыть файл, то в ответ должен прийти пакет данных (структура scb_msg_t без данных за ней). И вот клиент QNX ее получает, а в Qt сигнал readyRead() не получаю. В чем может быть загвостка?
|
|
|
977
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 16:04
|
вот как лучше сделать? я думаю, сначала пакета ставить сигнатуру, например 'PACKBGN',/0, потом uint16_t lenght, потом данные если есть, в конце 'PACKEND',/0. может в будущем и CRC. теперь я так понимаю, сначала делаю peek. далее надо найти в памяти сигнатуру начала. потом получить размер оставшийся, и копировать в буфер данные с сокета пока не получу сигнатуру конца или размер принятых данных не будет равен размеру, который шел после сигнатуры начала. так делать? а если сигнатура обрывается где то по середине? тогда какого размера брать буфер чтения?
|
|
|
978
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 15:20
|
вот кусок кода чтения клиента под QNX где все работает: (хотя без каких либо проверок пока) void * thread_func(void * params) { net_client_t * client = (net_client_t *)params;
ssize_t received; ssize_t header_size = sizeof(scb_msg_t); ssize_t waitsize; uint32_t flag = MSG_PEEK;
while(1) //endless loop { while(1) { flag = MSG_PEEK | MSG_WAITALL; waitsize = header_size; received = recv(client->socket_descriptor,client->read_buffer,waitsize,flag); if(received > 0) { if(((scb_msg_t*)client->read_buffer)->size>client->read_buffer_size) { printf("%s:%d receive error: header->size[%d]>read_buffer_size[%d]!\n", client->remote_host.c_str(),client->remote_port, ((scb_msg_t*)client->read_buffer)->size,client->read_buffer_size); break; }
flag = MSG_WAITALL;
if(((scb_msg_t*)client->read_buffer)->size==0) { printf("%s:%d receive error: header->size==0, ignoring\n",client->remote_host.c_str(),client->remote_port); received = recv(client->socket_descriptor,client->read_buffer,header_size,flag); continue; }
waitsize = (ssize_t)((scb_msg_t*)client->read_buffer)->size;
received = recv(client->socket_descriptor,client->read_buffer,waitsize,flag); if(received == waitsize) { if(client->on_data_received) client->on_data_received(client,client->read_buffer,received); } else break; } else break; }
client_disconnect(client); sleep(2); client_connect(client); }
#if defined(__WINDOWS__) return 0; #else return NULL; #endif }
В этом коде все пакеты приходят правильно и целиком...
|
|
|
981
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 14:23
|
предложите ваш вариант? сервер уже написан (писал не я) и работает. т.е. в начало и конец заголовка положить сигнатуру? потом в очередном peek её искать? если нашёл, тогда уже читать как выше изложено?
|
|
|
982
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 14:13
|
выравнивание мы привели к одинаковому значению. например проблем на qnx клиенте не возникает, и все данные приходят как надо. но механизм приема там немного другой в силу специфики ОС.
|
|
|
983
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 13:59
|
Я так и не понял к чему то что по ссылке? А наш протокол довольно протостой. Есть заголовок в виде структуры, у которой несколько полей. typedef struct { uint32_t family; //Семейство uint32_t action; //Действие uint32_t size; //размер пакета time_t time; int32_t p1; int32_t p2; int32_t p3; int32_t p4; int32_t p5; int32_t p6; int32_t p7; int32_t p8; } scb_msg_t;// __attribute__ ((packed));
Как видно, в size заклдаывается длина пакета (заголовок + данные если есть за ним). На клиенте мне нужно получить даголовок и данные если есть за ним.
|
|
|
984
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 12:25
|
интересно, что некоторые пакеты не приходят, по карайней мере я не получаю сигнал readyRead, когда например в другой программе(которая работает по этому же протоколу но написанной под QNX на socket API) все приходит. В чем может быть проблема? В данном случае, я ожидаю пакет длиной 48 байт. Ощущение ,что пакеты меньше или равные 48 байтам мне не доходят.
|
|
|
985
|
Qt / Работа с сетью / Re: Чтение с сокета без QDataStream
|
: Июнь 29, 2011, 11:56
|
Вот что у меня получилось. void QGenericArmClient::readyRead() { if(fblockSize==0) //читаем заголовок пакета (остальное остается в буфере) { if(fsocket->bytesAvailable()<sizeof(scb_msg_t)) return; //если данных меньше чем заголовок - игнорируем freceived = fsocket->read(frawBuffer,sizeof(scb_msg_t)); //получаем заголовок if(fframeHeader->size==0) //если в заголовке стоит длина 0, игнорируем этот пакет { freceived = 0; return; } }
int bytesAvail = fsocket->bytesAvailable(); //сколько еще в буфере данных? if(bytesAvail) //если что то есть { fblockSize = fsocket->read(&frawBuffer[freceived],bytesAvail); //читаем очередной блок данных со смещением на уже принятые freceived+=fblockSize; //обновляем колво принятых данных }
if(freceived>=fframeHeader->size) //если данных достаточно { fmutex->lock(); qMemCopy(fdestBuffer,frawBuffer,freceived); //копируем в результирующий буфер fmutex->unlock(); emit frameReceived(freceived); //даем сигнал о том что данные приняты freceived = 0; //обнуляем счетчик принятых данных } }
Все работает, но такой вопрос, может ли быть такая ситуация, когда в следующем int bytesAvail = fsocket->bytesAvailable(); //сколько еще в буфере данных? if(bytesAvail) //если что то есть { fblockSize = fsocket->read(&frawBuffer[freceived],bytesAvail); //читаем очередной блок данных со смещением на уже принятые freceived+=fblockSize; //обновляем колво принятых данных } может прийти часть следующего пакета?
|
|
|
989
|
Qt / Пользовательский интерфейс (GUI) / Как узнать, какой пункт меню был выбран?
|
: Июнь 23, 2011, 14:30
|
Формируется главное меню окна динамически. К примеру, есть несколько клиентов, для каждого клиента свой пункт меню. Все пункты меню нужно привязать к одному слоту этого окна, в котором нужно произвести некоторые предварительные настройки программы, а затем обратиться к конкретному клиенту. Как это сделать?
|
|
|
|
|