首页 > 编程语言 > 详细

计通网实验的准备工作(2):成帧实现(C语言)

时间:2014-04-13 10:18:45      阅读:611      评论:0      收藏:0      [点我收藏+]

上一次解决编码问题,这里解决成帧问题。

在成帧的问题上,有很多需要解决的问题。首要的一点是:如何来定义数据的开头和结尾。

因为实验原因,这里采用最简单的方式:在数据的开头的结尾加入字节流01111110,在正式的数据内容中,凡是出现5个1,就在后面补一个0.

第一个难点:如何进行流量的控制?

这里同样采用最简单的停等协议。将帧按照0~7进行编号,在帧的前3位记录帧的编号。发送方发送第一个帧后,等待接收方的响应。如果超时,则重发。接收方收到消息后,发送需要的下帧的编号,如果超时没有得到响应,则重发。在确认第一帧发送完成后,发送方以后发送的内容只有得到确认才继续发送。

第二个难点:检错码

这里使用经常使用的CRC校验码。

实验本来不要求使用完全的程序控制。因此,我使用小程序完成专门的任务,然后使用bat或者shell脚本将小工具链接起来,达到智能的目的。

第一个是CRC的实现。我将常用的命令写到CRC.h的头文件中。

// CRC.h
#ifndef CRC_H
#define CRC_H

#define G_LENGTH 5
#include <stdio.h>
static short G[G_LENGTH] = {1, 0, 0, 1, 1};
short* getRemainder(short* frame, int length);
int getFileLength(FILE *fp);

#endif

实现如下:

// CRC.c
#include <stdio.h>
#include "CRC.h"
#include <malloc.h>

short* getRemainder(short* frame, int length)
{
	int i, j, k;
	short step[G_LENGTH];
	short* remainder;
	remainder = (short*)malloc(sizeof(short) * (G_LENGTH - 1));
	
	for (i = 0; i < G_LENGTH; i++)
		step[i] = frame[i];

	for (i = 0; i < length - G_LENGTH + 1; i++)
	{
		if (step[0] == 0)
		{
			for (j = 0; j < 4; j++)
			{
				step[j] = step[j + 1] ^ 0;
			}
		}
		else if (step[0] == 1)
			for (j = 0; j < 4; j++)
				step[j] = step[j + 1] ^ G[j + 1];
		
		if (i < length - G_LENGTH)
			step[4] = frame[i + 5];
	}

	for (i = 0; i < 4; i++)
		remainder[i] = step[i];

	return remainder;
}

int getFileLength(FILE *fp)
{
	int length;
	if (fp == NULL)
		return -1;
	fseek(fp, 0L, SEEK_END);
	length = ftell(fp);
	fseek(fp, 0L, SEEK_SET);
	return length;
}

接下来是添加CRC校验码的实现(addcrc.c)

// addCRC.c
#include "CRC.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	FILE* frameFile;
	FILE* writeFrame;
	int length = 0;
	int i = 0;
	short* frame;
	short* add;
	char c;

	if ((frameFile = fopen(argv[1], "r")) == NULL)
	{
		fprintf(stderr, "Cannot open %s!\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	length = getFileLength(frameFile);
	frame = (short*)malloc(sizeof(short) * (length + G_LENGTH - 1));
	while ((c = getc(frameFile)) != EOF)
	{
		if (c == ‘0‘)
			frame[i++] = 0;
		else if (c == ‘1‘)
			frame[i++] = 1;
		else
		{
			fprintf(stderr, "Illegal character!\n");
			free(frame);
			fclose(frameFile);
			exit(EXIT_FAILURE);
		}
	}
	for (i = 0; i < G_LENGTH; i++)
		frame[length + i] = 0;
	add = getRemainder(frame, length + G_LENGTH - 1);

	fclose(frameFile);

	for (i = 0; i < G_LENGTH - 1; i++)
		frame[length + i] = add[i];

	if ((writeFrame = fopen(argv[1], "w")) == NULL)
	{
		fprintf(stderr, "Cannot open frame.txt!\n");
		exit(EXIT_FAILURE);
	}

	for (i = 0; i < length + G_LENGTH - 1; i++)
		if (frame[i] == 0)
			fprintf(writeFrame, "0");
		else
			fprintf(writeFrame, "1");

	fclose(writeFrame);
	free(frame);
	free(add);

	return 0;
}
addflag.c用于添加开始和结尾的标记以及5个1后面加0:

// addflag.c
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "CRC.h"

void addFlag(FILE *fp);
int main(int argc, char* argv[])
{
	FILE *frameFile;
	short* frame;
	int i;
	char c;
	int numOfOne, len;

	if ((frameFile = fopen(argv[1], "r")) == NULL)
	{
		fprintf(stderr, "Cannot open file %s\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	len = getFileLength(frameFile);
	frame = (short*)malloc(sizeof(short) * len);

	i = 0;
	while ((c = getc(frameFile)) != EOF)
	{
		if (c == ‘1‘)
			frame[i++] = 1;
		else if (c == ‘0‘)
			frame[i++] = 0;
		else
		{
			fprintf(stderr, "Illegal character!\n");
			fclose(frameFile);
			free(frame);
			exit(EXIT_FAILURE);
		}
	}

	fclose(frameFile);

	if ((frameFile = fopen(argv[1], "w")) == NULL)
	{
		fprintf(stderr, "Cannot open file %s\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	addFlag(frameFile);
	numOfOne = 0;
	for (i = 0; i < len; i++)
	{
		if (numOfOne == 5)
		{
			fprintf(frameFile, "0");
			numOfOne = 0;
		}
		if (frame[i] == 1)
		{
			fprintf(frameFile, "1");
			numOfOne++;
		}
		if (frame[i] == 0)
		{
			fprintf(frameFile, "0");
			numOfOne = 0;
		}
	}
	addFlag(frameFile);

	fclose(frameFile);
	free(frame);

	return 0;
}

void addFlag(FILE *fp)
{
	int i;

	fprintf(fp, "0");
	for (i = 0; i < 6; i++)
		fprintf(fp, "1");
	fprintf(fp, "0");
}
pick.c用于挑选指定的内容到帧,并添加编号:

// pick.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "CRC.h"

#define FRAME_LEN 32

int main(int argc, char* argv[])
{
	FILE* outFile;
	FILE* frameFile;
	int numOfFrame;
	short* frame;
	char c;
	int frameLength;
	int i;

	if (argc != 2)
	{
		printf("Usage: makeframe numOfFrame\n");
		exit(0);
	}

	numOfFrame = atoi(argv[1]);

	if ((outFile = fopen("out.txt", "r")) == NULL)
	{
		fprintf(stderr, "Cannot open file: out.txt\n");
		exit(EXIT_FAILURE);
	}

	frame = (short*)malloc(sizeof(short) * FRAME_LEN);
	frameLength = 0;

	fseek(outFile, numOfFrame * FRAME_LEN, SEEK_SET);
	while ((c = getc(outFile)) != EOF && frameLength < FRAME_LEN)
	{
		if (c == ‘1‘)
			frame[frameLength++] = 1;
		else if (c == ‘0‘)
			frame[frameLength++] = 0;
		else
		{
			fprintf(stderr, "Illegal character!\n");
			fclose(outFile);
			fclose(frameFile);
			free(frame);
			exit(EXIT_FAILURE);
		}
	}

	if (c == EOF)
		printf("End of the file!\n");

	fclose(outFile);

	if ((frameFile = fopen("frame.txt", "w")) == NULL)
	{
		fprintf(stderr, "Cannot open file: frame.txt\n");
		exit(EXIT_FAILURE);
	}

	for (i = 2; i >= 0; i--)
	{
		if (numOfFrame & (1 << i))
			fprintf(outFile, "1");
		else
			fprintf(outFile, "0");
	}

	for (i = 0; i < frameLength; i++)
		fprintf(frameFile, "%d", frame[i]);

	fclose(frameFile);
	free(frame);

	return 0;
}
removeflag.c用于在数据流中找到帧,并去除标记,且去除5个1后面的0:

// removeflag.c
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "CRC.h"

static char* flag = "01111110";
void moveToFlag(FILE *fp);
int isFlag(FILE *fp);

int main(int argc, char* argv[])
{
	FILE* frameFile;
	int len;
	short* frame;
	int numOfOne = 0;
	int realLen = 0, i = 0;
	char c;

	if ((frameFile = fopen(argv[1], "r")) == NULL)
	{
		fprintf(stderr, "Cannot open file %s\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	len = getFileLength(frameFile);
	frame = (short*)malloc(sizeof(short) * len);

	moveToFlag(frameFile);
	while ((c = getc(frameFile)) != EOF)
	{
		if (c == ‘1‘)
		{
			frame[i++] = 1;
			numOfOne++;
		}
		else if (c == ‘0‘)
		{
			frame[i++] = 0;
			numOfOne = 0;
		}
		else
		{
			fprintf(stderr, "Illegal character!\n");
			fclose(frameFile);
			free(frame);
			exit(EXIT_FAILURE);
		}
		realLen++;

		if (numOfOne >= 5)
		{
			c = getc(frameFile);
			if (c == ‘1‘)
			{
				printf("Appears 6 one, Illegal!\n");
				fclose(frameFile);
				free(frame);
				exit(0);
			}
			else if (c == ‘0‘)
				numOfOne = 0;
			else
			{
				fprintf(stderr, "Illegal character!\n");
				fclose(frameFile);
				free(frame);
				exit(EXIT_FAILURE);
			}
		}
		if (isFlag(frameFile))
			break;
	}
	fclose(frameFile);
	
	if ((frameFile = fopen(argv[1], "w")) == NULL)
	{
		fprintf(stderr, "Cannot open file %s\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	for (i = 0; i < realLen; i++)
	{
		if (frame[i] == 1)
			fprintf(frameFile, "1");
		else if (frame[i] == 0)
			fprintf(frameFile, "0");
	}
	fclose(frameFile);
	free(frame);

	return 0;
}

int isFlag(FILE *fp)
{
	int i;
	char c;

	c = getc(fp);
	if (c == EOF)
	{
		printf("Cannot find flag!\n");
		exit(0);
	}
	if (c != ‘0‘)
	{
		fseek(fp, -1, SEEK_CUR);
		return 0;
	}
	for (i = 0; i < 6; i++)
	{
		c = getc(fp);
		if (c != ‘1‘)
			break;
	}
	if (i < 6)
	{
		fseek(fp, -i - 2, SEEK_CUR);
		return 0;
	}

	fseek(fp, -7, SEEK_CUR);
	return 1;
}

void moveToFlag(FILE *fp)
{
	char c;
	while (!isFlag(fp))
	{
		c = getc(fp);
		if (c == EOF)
		{
			printf("Cannot find flag!");
			exit(0);
		}
	}
	fseek(fp, 8, SEEK_CUR);
}
checkcrc.c用于检查帧的错误并生成相应的ack内容:

// checkcrc.c
#include "CRC.h"
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	FILE* frameFile;
	FILE* ackFile;
	short* frame;
	int length;
	int i, j;
	char c, temp;
	short* remainder;

	if ((frameFile = fopen(argv[1], "r")) == NULL)
	{
		fprintf(stderr, "Cannot open file %s!\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	if ((ackFile = fopen("ack.txt", "w")) == NULL)
	{
		fprintf(stderr, "Cannot open file ack.txt!\n");
		exit(EXIT_FAILURE);
	}

	length = getFileLength(frameFile);
	frame = (short*)malloc(sizeof(short) * length);

	i = 0;
	while ((c = getc(frameFile)) != EOF)
	{
		if (c == ‘0‘)
			frame[i++] = 0;
		else if (c == ‘1‘)
			frame[i++] = 1;
		else
		{
			fprintf(stderr, "Illegal character!\n");
			fclose(frameFile);
			free(frame);
			exit(EXIT_FAILURE);
		}
	}

	remainder = getRemainder(frame, length);

	for (i = 0; i < G_LENGTH - 1; i++)
		if (remainder[i] != 0)
			break;

	fseek(frameFile, 0, SEEK_SET);
	c = 0;
	for (j = 2; j >= 0; j--)
	{
		if (getc(frameFile) == ‘1‘)
		{
			c |= (1 << j);
		}
	}

	if (i == G_LENGTH - 1)
	{
		printf("Yes, you get right frame!\n");
		c++;
	}
	else
		printf("No, you get a wrong frame!\n");

	for (i = 2; i >= 0; i--)
	{
		temp = c & (1 << i) ? 1 : 0;
		for (j = 0; j < 5; j++)
			fprintf(ackFile, "%d", temp);
	}

	fclose(frameFile);
	free(frame);
	free(remainder);

	return 0;
}
将以上程序组合:

1、makeframe.bat用于生成帧,

@echo off
if "%1" == "" (echo 请输入帧号!
		echo 用法:makeframe 帧号
		goto A)

pick %1
addcrc frame.txt
addflag frame.txt
notepad frame.txt

:A
2、getframe.bat用于接收帧并生成ack,

@echo off
removeflag frame.txt
checkcrc frame.txt
notepad ack.txt

以上就是为这次实验的全部准备内容了。






计通网实验的准备工作(2):成帧实现(C语言),布布扣,bubuko.com

计通网实验的准备工作(2):成帧实现(C语言)

原文:http://blog.csdn.net/pdcxs007/article/details/22929609

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!