У меня есть блок MCU, подключенный к локальной сети. Это устройство отправляет данные статуса через сокет TCP 100 раз в секунду. В том же сокете я могу также выдавать команды и данные.
Я пытаюсь написать простой TCP-клиент, который мог бы подключиться к устройству, захватить данные и запросить команды отправки. В настоящее время я могу отправлять команды без проблем (команды отправляются как строки, и это работает). Моя проблема - прием данных из устройства FROM.
Я знаю из руководства по эксплуатации, что сначала данные должны быть 32-битными целыми числами, а затем массивом примерно 30 удвоений)
Я устанавливаю новый поток, который я хочу последовательно перехватить данные и обработать их:
void *com::setListenerSocket(void* threadSocketData) {
struct socketData *sockData;
sockData = (socketData*)threadSocketData;
com::tcp_client cListener;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=12500;
// setsockopt(cListener, IPPROTO_TCP, SO_RCVTIMEO, (char *)timeout, sizeof(timeout)); //no effect
cListener.connect(sockData->host , sockData->port);
cout << "listener thread started" << endl;
cout << "host=" << sockData->host << " at port=" << sockData->port << endl;
cListener.send_data("Listener Reporting\n");
while(listenerRun){
listenerHB++;
cout << endl <<"***************************** BGN *************************************************************"<< endl;
char *received = new char[PACKETSIZE];
cListener.receive(PACKETSIZE, received);
unsigned int test;
test = (uint32_t) received;
cout << "received=" << test << endl;
for(int i = 0; i< PACKETSIZE ; ++i)
cout << received[i] << ", ";
cout << endl <<"***************************** END *********************************************"<< endl;
robotPacket data;
//parseData(received, &data);
//usleep(1 MS);
}
cout << "listener signing out" << endl;;
pthread_exit(NULL);
}
и метод слушателя:
void com::tcp_client::receive(int size, char* buffer) {
unsigned int bytecnt = 0, archive = 1;
while(bytecnt < (unsigned int)size) {
// bytecnt += recv(sock , &buffer[bytecnt] , size-bytecnt , 0);
bytecnt += recv(sock , buffer , size-bytecnt , MSG_WAITALL);
}
unsigned int test;
test = buffer[0];
cout << "value=" << test << "¤" << endl;
}
Я взял указатель на начало буфера и отбросил его на uint32_t, но результат полностью ошибочен (я знаю, что это должна быть длина пакета, но она легко распространяется на миллионы миллионов)
Когда я использую команду nl: nc -l 12354 Я могу написать текст в свою программу, и все правильно
EDIT: Встреча с кем-то более опытным: РЕШЕННО: я не могу опубликовать решение самостоятельно, поэтому я поставлю его здесь, если кто-то столкнется с аналогичной проблемой.
Прежде всего, я ожидал, что сокет будет автоматически обрабатываться там, где начинается одна передача, а где его конец - что не так, как указал Базиль Старинкевич. Тем не менее, TCP гарантирует, что данные будут поступать последовательно, и ничего не потеряно, поэтому я могу с уверенностью предположить, что за 500 байтов, обещанных, я получу 500 байтов или что бы это ни было.
Во-вторых, данные поступают в большой эндиант - также, как указал Базиль. Я немного перепутал, но все же имел неправильный результат, но...
Наконец, у меня была другая проблема с типом. Я использовал char *, в то время как данные являются символами unsigned. Замена буферов char * с unsigned char * решила проблему декодирования.
Это может быть решением для всех, кто получает интерфейс со старыми электронными разработчиками, которые общаются по локальной сети.
Думаю, этот случай можно считать закрытым, если кто-то пишет то, что я написал выше, в аккуратной форме.
Вы можете проверить tcpclient (http://cr.yp.to/ucspi-tcp/tcpclient.html). Вы можете просто запустить свою программу C/C++ под tcpclient - т.е. Tcpclient вызовет вашу программу и откроет tcp-соединение с сервером, а также передаст вашу программу stdout на сервер и выведет на сервер вывод на вашу программу stdin. Самое приятное в том, что вы делаете это так, что вы можете позволить tcpclient для всех тяжелых подъемов до установки сокета и т.д., И вы можете сосредоточиться на основной функции вашей программы.
recv
может потерпеть неудачу с отрицательнымbytecnt