// EthernetFrame.cpp Main的实现
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
//encap.h
const int MAXLENGTH = 1500; // 帧最大长度
const int MINLENGTH = 46; // 帧最小长度
const char destination[] = { // 目的地址
char(0xFF), char(0xFF), char(0xFF),
char(0xFF), char(0xFF), char(0xFF)
};
const char source[] = { // 源地址
char(0x00), char(0x16), char(0x76),
char(0xB4), char(0xE4), char(0x77)
};
class Encap //封装帧类
{
public:
void HeaderEncap(fstream& file); // 完成前导码到源地址的四项封装
int DataDeal(fstream& file, string inputStr); // 处理数据字段
void Encapsulate(fstream& file, string inputStr, int length); // 完成剩余封装
};
//CRC8.h CRC8校验的实现
/************************************************************************/
/* 功能: CRC8校验
/* 输入参数: crc:CRC8的校验值;data待检验的字符串
/************************************************************************/
static unsigned char checkCRC(unsigned char& crc, unsigned char data) // crc数据设为引用调用
{
for (unsigned char i = 0x80; i > 0; i >>= 1) // 进行循环,每轮进行8次循环,处理一个字节
{
if ((crc & 0x80) != 0) // 首位为1则移位,并进行异或
{
crc <<= 1; // 左移一位
if ( (data & i) != 0) // 如果新读入的数据为1,将最低位置1
{
crc |= 1;
}
crc ^= 0x07; // 首位移出,对低8位进行异或运算,7的二进制为0000,0111
}
else // 首位为0,只移位,不进行异或运
{
crc <<= 1; // 左移一位
if ( (data & i) != 0) // 如果新读入的数据为1,将最低位置1
{
crc |= 1;
}
}
}
return crc;
}
//Encap.cpp 封装帧类的实现
using namespace std;
/************************************************************************/
/* 功能: 完成前导码到源地址的四项封装
/* 输入参数: fstream对象
/************************************************************************/
void Encap::HeaderEncap(fstream& file)
{
file.seekg(0,ios::end); //将读指针移到文件末尾
for(int i=0;i<7;i++) //写入B的前导码和B的帧前定界符
file.put((char)0xaa);
file.put((char)0xab);
file.write(destination,6); //写入目的地址
file.write(source, 6); //写入源地址
}
/************************************************************************/
/* 功能: 处理数据字段
/* 输入参数:file:fstream对象;inputstr:等待封装的字符串
/************************************************************************/
int Encap::DataDeal(fstream& file, string inputStr)
{
int packTotal = 0;
int length = inputStr.length();
if(length <= MINLENGTH) //如果输入文件长度不足46B,则用'0'补足
{
if (length < MINLENGTH)
{
for(int j = 0; j < MINLENGTH - length; j++)
inputStr += '0';
cout << "数据字段小于46,将封装成一个帧" <<endl;
}
else
{
cout << "数据字段等于46,将封装成一个帧" <<endl;
}
packTotal = 1;
Encapsulate(file, inputStr, length); //将字符串内容写入到输出文件中
cout << "第1个帧封装完毕!" << endl;
}
else
{
int packNum = 1;
if (length > MAXLENGTH) //如果输入文件长度大于最大值
{
packNum = length / MAXLENGTH;
if (length % MAXLENGTH) //计算封帧个数
{
packNum++;
}
packTotal = packNum;
cout << "数据字段大于1500B,将封装成" << packNum << "个帧" <<endl;
string divideStr; //本次拆分好的数据
string leftStr = inputStr; //剩余未封装的数据
packNum = 1;
while (length > MAXLENGTH)
{
divideStr = leftStr.substr(0,MAXLENGTH);
cout << divideStr << endl;
leftStr = leftStr.substr(MAXLENGTH,length);
length = leftStr.length();
Encapsulate(file, divideStr, MAXLENGTH);
cout << "第" << packNum << "个帧封装完毕!" << endl;
packNum++;
}
if(length < MINLENGTH)
{
for(int j = 0; j < MINLENGTH - length; j++)
leftStr += '0';
}
Encapsulate(file, leftStr, length); //将剩余字符串封装,length为字符串的真实长度,不是补足'0'后的长度
cout << leftStr << endl;
cout << "第" << packNum << "个帧封装完毕!" << endl;
packNum++;
}
else //如果输入文件长度小于等于最大值
{
if (MAXLENGTH== length)
{
cout << "数据字段等于1500B,将封装成1个帧" <<endl;
}
else
{
cout << "数据字段介于46B和1500B之间,将封装成1个帧" <<endl;
}
packTotal = 1;
Encapsulate(file, inputStr, length); //将字符串封装
cout << "第" << packNum << "个帧封装完毕!" << endl;
packNum++;
}
}
return packTotal;
}
/************************************************************************/
/* 功能: 完成剩余封装
/* 输入参数:file:fstream对象;inputstr:等待封装的字符串;
/* length 数据内容长度
/************************************************************************/
void Encap::Encapsulate(fstream& file, string inputStr, int length)
{
HeaderEncap(file); // 封装头
const char* inputChar = inputStr.data();
char inputLength[2];
inputLength[0] = length >> 8;
inputLength[1] = length & 0xFF;
file.put(inputLength[0]); //将字符串长度值前八位放入inputLength[0]
file.put(inputLength[1]); //后八位放入inputLength[1]
file.write(inputChar, inputStr.length()); //inputChar可能被填充,因此它的长度不是原来的数据长度length
unsigned char CRC8 = char(0x00); // CRC8初始化校验码
int i = 0;
for(i = 0; i < 6; i++) // 校验目的地址、源地址
checkCRC(CRC8, destination[i]);
for(i = 0; i < 6; i++)
checkCRC(CRC8, source[i]);
checkCRC(CRC8, inputLength[0]); // 校验长度
checkCRC(CRC8, inputLength[1]);
for(i = 0; i < inputStr.length(); i++) // 校验字符串
checkCRC(CRC8, inputChar[i]);
checkCRC(CRC8, 0x00); // 在校验对象后加0x00,校验完毕
file.put(CRC8); // 将CRC8校验值封装到帧中
}
void main(int argc, char* argv[])
{
if(argc != 3) // 命令行参数输入
{
cout << "命令参数个数有误,请确认后重新输入" << endl;
cout << "请按以下格式输入:EthernetFrame.exe -e/-u filename" << endl;
return;
}
if (!strcmp(argv[1], "-e")) // 封装帧
{
cout << "封装帧" <<endl;
cout << "请输入一段信息(请输入两次回车表示结束)" <<endl;//VC6.0 Bug
string inputStr;
getline(cin, inputStr);
fstream file(argv[2],ios::out|ios::binary|ios::app);//ios::out|
if (!file.is_open())
{
cout << "无法打开帧封装包文件,请检查文件是否存在并且未损坏" << endl;
exit(0);
}
Encap eFrame;
int packTotal = eFrame.DataDeal(file, inputStr);
for (int i = 0; i < packTotal; i++)
{
cout << endl << "发送第 " << i + 1 << " 个帧" << endl;
cout << endl;
}
file.close();
}
}
网络高级软件编程(Ethernet帧的封装)
4星 · 超过85%的资源 需积分: 10 50 浏览量
2011-11-26
19:32:05
上传
评论 1
收藏 926KB RAR 举报
qq649007321
- 粉丝: 0
- 资源: 2
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈