文章目录
- 参考
- 代码
- 结果展示
参考
这篇文章给的代码也能用 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
代码
这里的byte
是unsigned 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;//启动Winsockif (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;//启动Winsockif (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;
}