我有一个连接到本地网络的MCU单元。该设备通过TCP套接字每秒发送100次状态数据。在同一个套接字上,我也可以发出命令和数据。
我正在尝试编写一个简单的TCP客户端,可以连接到设备,获取数据,如果请求发送命令。目前我可以毫无问题地发送命令(命令作为字符串发送,这是有效的)。我的问题是从设备接收数据。
我从设备手册中知道数据首先应该是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我可以在我的程序中写入文本,一切正确
编辑:与更有经验的人会面: 解决:我不能自己发布解决方案,所以我会把它放在这里以防有人遇到类似的问题。首先,我希望套接字能够自动处理单个传输开始的位置以及结束的位置 - 这是不正确的,正如Basyle Starynkevitch指出的那样。但是,TCP确保数据按顺序进行并且没有任何丢失,因此我可以安全地假设承诺的500字节我将获得500字节或其他任何内容。
其次,数据是以大尾数形式出现的 - 巴塞尔也指出了这一点。我做了一点点转移,但仍然有错误的结果,但......
最后,我遇到了类型转换的另一个问题。我使用char *而数据是unsigned char。 用unsigned char *替换缓冲区char *解决了解码问题。
对于那些与通过局域网进行通信的旧电子设备接口的人来说,这可以是一个解决方案。
如果有人以简洁的形式发布我上面写的内容,我想这个案例可以被认为是关闭的。
答案 0 :(得分:0)
您可能想要查看tcpclient(http://cr.yp.to/ucspi-tcp/tcpclient.html)。您可以在tcpclient下运行您的C / C ++程序 - 即tcpclient将生成您的程序并打开与服务器的tcp连接,并将程序的stdout传送到服务器,并将服务器的输出管道输出到程序的stdin。这样做的好处是你可以让tcpclient完成所有繁重的任务,就像设置套接字等一样,你可以专注于你的程序的核心功能。