c++ - 在C++中通过套接字接收二进制数据

标签 c++ linux sockets binary

我有一个连接到本地网络的 MCU 单元。该设备每秒通过 TCP 套接字发送其状态数据 100 次。通过同一个套接字,我还可以发出命令和数据。

我正在尝试编写一个简单的 TCP 客户端,它可以连接到设备、抓取数据并根据请求发送命令。目前我可以毫无问题地发送命令(命令作为字符串发送,这有效)。我的问题是从设备接收数据。

我从设备手册中知道数据应该首先是一个 32 位整数,然后是大约 30 个 double 的数组)

我正在建立一个新线程,我想连续拦截数据并处理它:

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 确保数据按顺序传入并且不会丢失任何内容,因此我可以放心地假设对于 promise 的 500 字节,我将获得该 500 字节或其他任何内容。

其次,数据以大尾数法输入 - 也正如 Basyle 所指出的那样。我做了一些位移,但仍然得到了错误的结果,但是......

最后,我在类型转换方面遇到了另一个问题。我使用的是 char* 而数据是无符号字符。 将缓冲区 char* 替换为 unsigned char* 解决了解码问题。

对于任何想要与通过局域网进行通信的旧电子设备进行交互的人来说,这都是一个解决方案。

我想如果有人以简洁的形式发布我上面写的内容,这个案子就可以被认为结束了。

最佳答案

您可能想查看 tcpclient ( http://cr.yp.to/ucspi-tcp/tcpclient.html )。您可以简单地在 tcpclient 下运行 C/C++ 程序 - 即 tcpclient 将生成您的程序并打开到服务器的 tcp 连接,并将程序的标准输出通过管道传输到服务器,并将服务器的输出通过管道传输到程序的标准输入。这样做的好处是,您可以让 tcpclient 承担所有繁重的工作,例如设置套接字等,并且您可以专注于程序的核心功能。

关于c++ - 在C++中通过套接字接收二进制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21827065/

相关文章:

c++ - 在 QTableView 中将垂直标题的文本居中?

c# - 从 C# 应用程序执行 C++ 函数

linux - AppEngine SSL 从命令行失败

java - java中的TCP套接字

PHP、nodeJS 和 session

c# - 如何使用 C++ 杀死 C++ 进程并让它在杀死之前做一些事情

c++ - 有人可以为我解释这个函数的最后一个参数吗?

java - 将文件从 Tomcat Linux 移动到另一个 Linux 服务器

python - Raspberry Pi 3 通过 720p USB 摄像头提高 FPS

c - 利布夫 : SO_REUSEPORT issue in Linux