今天给程序加入了socket通讯

该代码示例展示了如何在Windows和Linux环境下使用socket进行网络通信,接收type16格式的字符串。在Windows中,它涉及WSAStartup和WSACleanup等函数;而在Linux中,使用的是socket、connect、recv等系统调用。程序处理接收到的数据,提取特定格式的字段并存储到一个受保护的数据队列中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前连接的是雷达,发送的是string类型字符串,现在需要接收type16类型字符串

windows下的socket接收type16类型的字符串

这里我封装了两个函数,receiveFromServer用于通信,extractSubstring用于截取通信字段(截取02开头到03中间的信号)

//调用socket连接 接收信号以2开头3结尾中间的type16进制数据
std::string extractSubstring(const std::string& input) {
    std::string str_sub;
    std::string str = input;
    str.erase(std::remove(str.begin(), str.end(), ' '), str.end()); //删除字符串中的空格 02 46 03 > 024603
    std::string fieldValue;
    std::string result;

    for (size_t i = 0; i < str.length(); i += 2) {
        fieldValue = str.substr(i, 2);
        str_sub = str_sub + fieldValue;
        if (str_sub.substr(0, 2) != "02") {
            str_sub = "";
        }
        if (str_sub.substr(0, 2) == "02" && str_sub.substr(str_sub.length() - 2) == "03") {
            if (str_sub.substr(2, 2) == "4e" ||
                str_sub.substr(2, 2) == "44" ||
                str_sub.substr(2, 2) == "43" ||
                str_sub.substr(2, 2) == "53" ||
                str_sub.substr(2, 2) == "54")
            {
                result += str_sub + "\n";
            }
            str_sub = "";
        }
    }
    return result;
}

std::mutex data_mutex;   // 数据锁
std::deque<std::string> data_queue;  // 数据队列

void str_socket_1(std::string ip, int ip_id) {
    // 初始化Winsock库
    WSADATA wsaData;
    int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (err != 0)
    {
        std::cout << "WSAStartup failed with error: " << err << std::endl;
        return;
    }

    // 创建套接字
    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
    {
        std::cout << "socket failed with error: " << WSAGetLastError() << std::endl;
        WSACleanup();
        return;
    }

    // 设置服务器地址和端口
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
    serverAddr.sin_port = htons(ip_id);

    // 连接到服务器 
    int ret = connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
    if (ret == SOCKET_ERROR)
    {
        std::cout << "connect failed with error: " << WSAGetLastError() << std::endl;
        closesocket(sock);
        WSACleanup();
        return;
    }

    // 循环接收数据
    while (true) {
        // 从服务器接收数据
        unsigned char recvData[32];
        ret = recv(sock, (char*)recvData, 32, 0);
        if (ret == SOCKET_ERROR)
        {
            std::cout << "recv failed with error: " << WSAGetLastError() << std::endl;
            break;
        }
        else
        {
            std::stringstream ss;
            for (int i = 0; i < ret; i += 2)
            {
                uint16_t value = (uint16_t)(recvData[i] << 8) | recvData[i + 1];
                ss << std::hex << std::setfill('0') << std::setw(4) << value << " ";
            }

            // 处理接收到的数据
            std::string str_sub_1 = extractSubstring(ss.str());
            {
                std::lock_guard<std::mutex> lock(data_mutex);
                data_queue.push_front(str_sub_1);
                if (data_queue.size() > 5) {
                    data_queue.pop_back();  // 删除队列末
                }
            }
        }
    }

    // 关闭套接字和Winsock库
    closesocket(sock);
    WSACleanup();
}

这里在windows下测试完成后需要转linux

这里是linux版本的socket 可以看到变更了头文件以及细微参数的变更 整体与windows都差不多

#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>
#include <iomanip>

std::deque<std::string> data_queue;  // 数据队列

//创建一个端口反复接收字段
void str_socket_1(std::string ip, int ip_id) {
    // 创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("socket");
        return;
    }

    // 设置服务器地址
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
    serverAddr.sin_port = htons(ip_id);

    // 连接到服务器
    int ret = connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (ret == -1) {
        perror("connect");
        close(sock);
        return;
    }

    // 循环接收数据
    while (true) {
        // 从服务器接收数据
        unsigned char recvData[32];
        ret = recv(sock, recvData, sizeof(recvData), 0);
        if (ret == -1) {
            perror("recv");
            break;
        }
        else if (ret == 0) {
            std::cout << "Connection closed by the server." << std::endl;
            break;
        }
        else {
            std::stringstream ss;
            for (int i = 0; i < ret; i += 2) {
                uint16_t value = (uint16_t)(recvData[i] << 8) | recvData[i + 1];
                ss << std::hex << std::setfill('0') << std::setw(4) << value << " ";
            }

            // 处理接收到的数据
            std::string str_sub_1 = extractSubstring(ss.str());
            {
                std::lock_guard<std::mutex> lock(data_mutex);
                data_queue.push_front(str_sub_1);
                if (data_queue.size() > 5) {
                    data_queue.pop_back();  // 删除队列末尾的数据
                }
            }
        }
    }

    // 关闭套接字
    close(sock);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士是只猫

开源使得世界变得更美丽

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值