C++中使用Winsock2 UDP Socket发送字节数据

参考

这篇文章给的代码也能用 https://blog.csdn.net/qq_36437446/article/details/106446172
CRC代码来自https://blog.csdn.net/huijunma2010/article/details/124151471

在线计算CRC http://www.ip33.com/crc.html

代码

这里的byteunsigned char ,1个字节

//#include<tchar.h>
#define _HAS_STD_BYTE 0
#include<numeric>
#include <cstddef>
#include <bitset>
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <WS2tcpip.h>
#include<string>
#include<cstring>
#include <windows.h>

#pragma comment(lib, "ws2_32.lib")
using namespace std;
const int nPort = 7799;
const string addRess = "127.0.0.1";


byte Reverse8(byte data)
{
    byte i;
    byte temp = 0;
    for (i = 0; i < 8; i++)
    {
        temp = (byte)(temp | (((data >> i) & 0x01) << (7 - i)));
    }
    return temp;
}


//CRC-8/MAXIM参数模型
byte GetCRC8(byte buffer[], int length)
{
    byte data;
    byte crc = 0x00; //初始值(16位举个例子0xFFFF,8位0xFF)
    int i;
    for (int j = 0; j < length; j++)
    {
        data = buffer[j];
        data = (byte)Reverse8(data); //输入是否反转,如果不需要则这句注释掉;
        crc = (byte)(crc ^ (data << 0)); //32位左移24位,16位左移8位,8位左移0位;
        for (i = 0; i < 8; i++)
        {
            if ((crc & 0x80) == 0x80)//16位 0x8000  8位 0x80
            {
                crc = (crc << 1) ^ 0x31;//多项式,没什么好说的;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    crc = Reverse8(crc);//输出是否需要反转,如果不需要则注释掉这句话,注意如果是16位则调用Reverse16(crc),8位调用Reverse8(crc)
    crc = crc ^ 0x00;// xor 异或值(与上面初始值类似,16位 0x0000  8位 0x00;
    return crc;
}




//炫技的成分大一点
//使用C语言里的struct和union来处理组帧和解帧特别漂亮
struct MagicFrame {
    union {
        byte notCRC[4+256+2];
        struct { byte FrameHead[4]; byte FixedNumber[256]; byte FrameIndex[2]; } notCRC_slice;
    } ;
    byte CRC;
};



int main()
{
    /*组帧:FrameHead和FixedNumber*/   
    struct MagicFrame FrameBuilder;
    for (int i = 0; i < 4; i++) {
        FrameBuilder.notCRC_slice.FrameHead[i] = static_cast <byte>(0x7A);
    }
    for (int i = 0; i < 256; i++) {
        FrameBuilder.notCRC_slice.FixedNumber[i] = static_cast <byte>(i);
    }
    /*组帧:FrameHead和FixedNumber*/



    WSAData wsd;
    SOCKADDR_IN siLocal;
    //启动Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
        cout << "WSAStartup Error = " << WSAGetLastError() << endl;
        return 0;
    }
    SOCKET soSend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (soSend == SOCKET_ERROR) {
        cout << "socket Error = " << WSAGetLastError() << endl;
        return 1;
    }
    siLocal.sin_family = AF_INET;
    siLocal.sin_port = htons(nPort);
    inet_pton(AF_INET, addRess.c_str(), &siLocal.sin_addr.S_un.S_addr);

    for (short int frame = 0; frame < 10; frame++) {

        /*填充FrameIndex*/
        void* p = &frame;
        byte* p1 = (byte*)(p);
        byte* p2 = (byte*)(p1 + 1);
        FrameBuilder.notCRC_slice.FrameIndex[0] = *p2;
        FrameBuilder.notCRC_slice.FrameIndex[1] = *p1;
        /*填充FrameIndex*/

        /*填充CRC*/
        FrameBuilder.CRC = GetCRC8(FrameBuilder.notCRC, _countof(FrameBuilder.notCRC) );
        /*填充CRC*/


        int nRet = sendto(soSend,
            (const char*)&FrameBuilder,
            sizeof(FrameBuilder),
            0,
            (SOCKADDR*)&siLocal,
            sizeof(SOCKADDR)
        );

        if (nRet == SOCKET_ERROR) {
            cout << "sendto Error " << WSAGetLastError() << endl;
        }
        else {
            cout << "toSend frame:" << frame << "success\n";
        }
        Sleep(1000);
    }
    closesocket(soSend);
    WSACleanup();
    return 0;
}


下面这份代码效果一样,但是不容易阅读

//#include<tchar.h>
#define _HAS_STD_BYTE 0
#include<numeric>
#include <cstddef>
#include <bitset>
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <WS2tcpip.h>
#include<string>
#include<cstring>
#include <windows.h>

#pragma comment(lib, "ws2_32.lib")
using namespace std;
const int nPort = 7799;
const string addRess = "127.0.0.1";

byte Reverse8(byte data)
{
    byte i;
    byte temp = 0;
    for (i = 0; i < 8; i++)
    {
        temp = (byte)(temp | (((data >> i) & 0x01) << (7 - i)));
    }
    return temp;
}


byte GetCRC8( byte buffer [],int length)
{
    byte data;
    byte crc = 0x00; //初始值(16位举个例子0xFFFF,8位0xFF)
    int i;
    for (int j = 0; j < length; j++)
    {
        data = buffer[j];
        data = (byte)Reverse8(data); //输入是否反转,如果不需要则这句注释掉;
        crc = (byte)(crc ^ (data << 0)); //32位左移24位,16位左移8位,8位左移0位;
        for (i = 0; i < 8; i++)
        {
            if ((crc & 0x80) == 0x80)//16位 0x8000  8位 0x80
            {
                crc = (crc << 1) ^ 0x31;//多项式,没什么好说的;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    crc = Reverse8(crc);//输出是否需要反转,如果不需要则注释掉这句话,注意如果是16位则调用Reverse16(crc),8位调用Reverse8(crc)
    crc = crc ^ 0x00;// xor 异或值(与上面初始值类似,16位 0x0000  8位 0x00;
    return crc;
}


int main()
{
    /*组帧:FrameHead和FixedNumber*/
    int FrameHead_len = 4;
    int FixedNumber_len = 256;
    int FrameIndex_len = 2;
    int CRC_len = 1;
    int len_arr[] = { FrameHead_len ,FixedNumber_len, FrameIndex_len ,CRC_len };
    int total_len = std::accumulate(len_arr, len_arr + _countof(len_arr), 0);
    byte FrameBuilder[4+256+2+1] = {};
    int offset_arr[4];
    partial_sum(len_arr, len_arr+_countof(len_arr), offset_arr);

    for (int i = 0; i < 4; i++) {
        FrameBuilder[i+0] = static_cast <byte>(0x7A);
    }
    for (int i = 0; i < 256; i++) {
        FrameBuilder[i + offset_arr[0]] = static_cast <byte>(i);
    }
    /*组帧:FrameHead和FixedNumber*/



    WSAData wsd;
    SOCKET soSend;
    int nRet = 0;
    SOCKADDR_IN siLocal;
    //启动Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
        cout << "WSAStartup Error = " << WSAGetLastError() << endl;
        return 0;
    }
    soSend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (soSend == SOCKET_ERROR) {
        cout << "socket Error = " << WSAGetLastError() << endl;
        return 1;
    }
    siLocal.sin_family = AF_INET;
    siLocal.sin_port = htons(nPort);
    inet_pton(AF_INET, addRess.c_str(), &siLocal.sin_addr.S_un.S_addr);
    
    for (short int frame = 0; frame < 10; frame++) {

        /*填充FrameIndex*/
        void* p = &frame;
        byte* p1 = (byte*)(p);
        byte* p2 = (byte*)(p1 + 1);
        FrameBuilder[0 + offset_arr[1]] = *p2;
        FrameBuilder[1 + offset_arr[1]] = *p1;
        /*填充FrameIndex*/

        /*填充CRC*/
        FrameBuilder[0+ offset_arr[2]] =GetCRC8(FrameBuilder,_countof(FrameBuilder)-1);
        /*填充CRC*/


        nRet = sendto(  soSend,
                        (const char*)&FrameBuilder,
                         _countof(FrameBuilder),
                        0,
                        (SOCKADDR*)&siLocal,
                        sizeof(SOCKADDR)
                        );
        
        if (nRet == SOCKET_ERROR) {
            cout << "sendto Error " << WSAGetLastError() << endl;
        }
        else {
            cout << "toSend frame:" << frame << "success\n";
        }
        Sleep(1000);
    }
    closesocket(soSend);
    WSACleanup();
    return 0;
}


结果展示

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值