C数组操作协议转换
C array manipulation protocol conversion
我正在尝试执行协议转换
第一个协议
| 1 byte (address) | 1 byte (function code) | 0-254 bytes (data) | 2 bytes ( CRC )|
第二个协议
| 2 bytes (address) | 2 bytes (0) | 2 bytes (length) | 1 byte (0) | 1 byte (function code) | 0-254 bytes (data) |
收到第一个协议帧,其数据应重新映射到第二个协议帧中
第一个协议的字节 0 应该映射到第二个协议的字节 0 和 1。
static int convert(uint8_t *buffer, int len, uint8_t* frame){
frame[0] = 0x00;
frame[1] = buffer[0];
frame[2] = 0x00;
frame[3] = 0x00;
frame[4] = 0x00;
frame[5] = len - 4 + 1;
frame[6] = 0x00;
frame[7] = buffer[1];
memcpy(&frame[8], &buffer[2], len-4);
return frame[5] + 6;
}
uint8_t buffIN[260]; // first protocol
uint8_t buffOUT[264]; // second protocol
/*READ DATA INT buffIN*/
//8 bytes received
// if frame is valid continue else signal error
int res = convert(&buffIN, 8 &buffOUT);
如果有人使用不同的方法请告诉我
您需要考虑进行协议转换的两个方面:传输的不同特征和数据的差异。最重要的传输特性是数据的字节顺序,尤其是关于转换器所在的处理器 运行。其他特征可能涉及字符集(纯 ASCII 与某种 Unicode 风格——或过去的 EBCDIC)、数值的大小、日期格式等。数据的差异包括字段顺序、字段存在和数据表示(映射一组值叠加到另一组值上)。
此外,大多数协议转换器都需要双向。
现在回过头来记住程序最基本的范式:输入-处理-输出。这种结构在协议转换中非常有用。您希望所有处理(无论方向如何)都以标准格式对经过清理的数据进行操作。因此,为一个独立于要转换的协议的协议数据包定义一个内部表示。对其进行设计以充分利用转换器的处理器。
然后写四个例程:
- 将协议 1 转换为内部格式
- 将内部格式转换为协议 1
- 将协议 2 转换为内部格式
- 将内部格式转换为协议 2
您的简化主线变为:
while(TRUE)
if (protocol 1 packet available)
convert it to internal format
perform any necessary processing
convert to protocol 2 and transmit
endif
if (protocol 2 packet available)
convert it to internal format
perform any necessary processing
convert to protocol 1 and transmit
endif
endwhile
这完全脱离了相互了解的两种协议转换,并且可以很容易地从一个或另一个切换到另一个,或者响应其中一个的变化。
现在以您的具体示例为例,我的内部结构如下所示:
typedef struct internalForm {
unsigned int address;
unsigned int function;
size_t payloadLength;
unsigned char payload[255];
} internalForm;
我的四种方法将具有这些原型:
#include <stdbool.h>
bool P1ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal);
size_t InternalToP1(const internalForm * internal, unsigned char *packet, size_t packetLength);
bool P2ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal);
size_t InternalToP2(const internalForm * internal, unsigned char *packet, size_t packetLength);
bool
return 只是表示输入转换失败。 'output' 函数 return 转换数据包的大小 - 或错误时为 0。
在更复杂的转换中,我实际上会对函数代码和其他 "enumerated" 字段等内容进行内部表示。转换例程将负责内部表示和特定于协议的表示之间的映射。
一个方向的完整实施可能是:
bool P1ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal)
{
internal->address = (unsigned int) packet[0];
internal->function = (unsigned int) packet[1];
// You need to write the function below. It could just be a look up
size_t dataLength = MapP1FunctionToPayloadLength(internal->function);
if (dataLength > sizeof(internal->payload))
return false;
// You need to write CheckCRC()
if (!CheckCRC(&packet[2], dataLength, &packet[2+dataLength]))
return false;
internal->payloadLength = dataLength;
memset(internal->payload, 0, sizeof(internal->payload));
memcpy(internal->payload, &packet[2], dataLength);
return true;
}
size_t InternalToP2(const internalForm * internal, unsigned char *packet, size_t bufferLength)
{
if (bufferLength < internal->payloadLength + 8)
return 0;
memset(packet, 0, bufferLength);
// Assumes little-endian representation, but it's not hard to see what
// to do for the alternative. And you should have an enum for the array
// indices.
packet[1] = internal->address & 0xff;
packet[5] = internal->payloadLength; // Not sure where your +1 is coming from
packet[7] = internal->function & 0xff;
memcpy(&payload[8], internal->payload, internal->payloadLength);
return internal->PayloadLength + 8;
}
对于您的简单示例来说,这似乎有些矫枉过正,但作为一个框架,它将导致非常强大的转换程序。转换错误将非常明显并且易于调试。输入输出转换,内部处理都可以独立单元测试。
最后,转换如下:
unsigned char inBuff[260], outBuff[264];
struct internalForm internal;
if (P1ToInternal(inBuff, sizeof(inBuff), &internal))
{
size_t len = InternalToP2(&internal, outBuff, sizeof(outBuff))
if (len)
transmitP2(outBuff, len);
}
我正在尝试执行协议转换
第一个协议
| 1 byte (address) | 1 byte (function code) | 0-254 bytes (data) | 2 bytes ( CRC )|
第二个协议
| 2 bytes (address) | 2 bytes (0) | 2 bytes (length) | 1 byte (0) | 1 byte (function code) | 0-254 bytes (data) |
收到第一个协议帧,其数据应重新映射到第二个协议帧中
第一个协议的字节 0 应该映射到第二个协议的字节 0 和 1。
static int convert(uint8_t *buffer, int len, uint8_t* frame){
frame[0] = 0x00;
frame[1] = buffer[0];
frame[2] = 0x00;
frame[3] = 0x00;
frame[4] = 0x00;
frame[5] = len - 4 + 1;
frame[6] = 0x00;
frame[7] = buffer[1];
memcpy(&frame[8], &buffer[2], len-4);
return frame[5] + 6;
}
uint8_t buffIN[260]; // first protocol
uint8_t buffOUT[264]; // second protocol
/*READ DATA INT buffIN*/
//8 bytes received
// if frame is valid continue else signal error
int res = convert(&buffIN, 8 &buffOUT);
如果有人使用不同的方法请告诉我
您需要考虑进行协议转换的两个方面:传输的不同特征和数据的差异。最重要的传输特性是数据的字节顺序,尤其是关于转换器所在的处理器 运行。其他特征可能涉及字符集(纯 ASCII 与某种 Unicode 风格——或过去的 EBCDIC)、数值的大小、日期格式等。数据的差异包括字段顺序、字段存在和数据表示(映射一组值叠加到另一组值上)。
此外,大多数协议转换器都需要双向。
现在回过头来记住程序最基本的范式:输入-处理-输出。这种结构在协议转换中非常有用。您希望所有处理(无论方向如何)都以标准格式对经过清理的数据进行操作。因此,为一个独立于要转换的协议的协议数据包定义一个内部表示。对其进行设计以充分利用转换器的处理器。
然后写四个例程:
- 将协议 1 转换为内部格式
- 将内部格式转换为协议 1
- 将协议 2 转换为内部格式
- 将内部格式转换为协议 2
您的简化主线变为:
while(TRUE)
if (protocol 1 packet available)
convert it to internal format
perform any necessary processing
convert to protocol 2 and transmit
endif
if (protocol 2 packet available)
convert it to internal format
perform any necessary processing
convert to protocol 1 and transmit
endif
endwhile
这完全脱离了相互了解的两种协议转换,并且可以很容易地从一个或另一个切换到另一个,或者响应其中一个的变化。
现在以您的具体示例为例,我的内部结构如下所示:
typedef struct internalForm {
unsigned int address;
unsigned int function;
size_t payloadLength;
unsigned char payload[255];
} internalForm;
我的四种方法将具有这些原型:
#include <stdbool.h>
bool P1ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal);
size_t InternalToP1(const internalForm * internal, unsigned char *packet, size_t packetLength);
bool P2ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal);
size_t InternalToP2(const internalForm * internal, unsigned char *packet, size_t packetLength);
bool
return 只是表示输入转换失败。 'output' 函数 return 转换数据包的大小 - 或错误时为 0。
在更复杂的转换中,我实际上会对函数代码和其他 "enumerated" 字段等内容进行内部表示。转换例程将负责内部表示和特定于协议的表示之间的映射。
一个方向的完整实施可能是:
bool P1ToInternal(const unsigned char *packet, size_t packetLength, internalForm * internal)
{
internal->address = (unsigned int) packet[0];
internal->function = (unsigned int) packet[1];
// You need to write the function below. It could just be a look up
size_t dataLength = MapP1FunctionToPayloadLength(internal->function);
if (dataLength > sizeof(internal->payload))
return false;
// You need to write CheckCRC()
if (!CheckCRC(&packet[2], dataLength, &packet[2+dataLength]))
return false;
internal->payloadLength = dataLength;
memset(internal->payload, 0, sizeof(internal->payload));
memcpy(internal->payload, &packet[2], dataLength);
return true;
}
size_t InternalToP2(const internalForm * internal, unsigned char *packet, size_t bufferLength)
{
if (bufferLength < internal->payloadLength + 8)
return 0;
memset(packet, 0, bufferLength);
// Assumes little-endian representation, but it's not hard to see what
// to do for the alternative. And you should have an enum for the array
// indices.
packet[1] = internal->address & 0xff;
packet[5] = internal->payloadLength; // Not sure where your +1 is coming from
packet[7] = internal->function & 0xff;
memcpy(&payload[8], internal->payload, internal->payloadLength);
return internal->PayloadLength + 8;
}
对于您的简单示例来说,这似乎有些矫枉过正,但作为一个框架,它将导致非常强大的转换程序。转换错误将非常明显并且易于调试。输入输出转换,内部处理都可以独立单元测试。
最后,转换如下:
unsigned char inBuff[260], outBuff[264];
struct internalForm internal;
if (P1ToInternal(inBuff, sizeof(inBuff), &internal))
{
size_t len = InternalToP2(&internal, outBuff, sizeof(outBuff))
if (len)
transmitP2(outBuff, len);
}