参考
这篇文章给的代码也能用 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;
//启动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;
}