⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sw.c

📁 linux1.0的源码
💻 C
字号:
/* sw.c */
/*
	使用停等协议来进行通信的例子,程序运行方法如下:

	sw s_s.dat s_r.dat sdl rdl 400
	sw r_s.dat r_r.dat rdl sdl 500

	400、500的延时很重要,如果设置太小,会导致信道忙,传输反而慢。
	设置太大,那么也会传输太慢。
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include <io.h>


#define	true 	1
#define	false 	0

#define	FILE_WRITE_PERMISSION	2
#define	FILE_READ_PERMISSION    4

char PHYSICAL_DATA_LINK_FILE_WRITE[12];
char PHYSICAL_DATA_LINK_FILE_READ[12];

enum protocol_event {
    PACKET_READY,
    FRAME_ARRIVAL,
    TIME_OUT,
    NO_EVENT,
    ChannelIdle,
    CheckSumError
};

typedef	char packet;

struct frame		/* frame structure */
{
    packet info;
    int seq;
    int ack;
};

packet buffer;

int NextFrameToSend;
int FrameExpected;
int PacketLength;
int waiting;
int network_layer_flag;

FILE *fps, *fpr;
int fps_length;

#define INTR 0X1C    /* The clock tick interrupt */

int	init_timer_value;	/* a second is 17.2 tick */

void interrupt ( *oldhandler)();

int timer_count = 0;
int timer_run_flag = false;
int delay_time;

void interrupt handler()
{
    if(timer_run_flag)
    {
        timer_count--;
    }

    oldhandler();		/* call the old routine */
}


char *event_string(enum protocol_event e, char *e_str)
{
    switch (e)
    {
    case PACKET_READY:
        strcpy(e_str, "PACKET_READY");
        break;
    case FRAME_ARRIVAL:
        strcpy(e_str, "FRAME_ARRIVAL");
        break;
    case TIME_OUT:
        strcpy(e_str, "TIME_OUT");
        break;
    case NO_EVENT:
        strcpy(e_str, "NO_EVENT");
        break;
    case ChannelIdle:
        strcpy(e_str, "ChannelIdle");
        break;
    case CheckSumError:
        strcpy(e_str, "CheckSumError");
        break;
    default:
        strcpy(e_str, "Unknow Event");
        break;
    }
    return e_str;
}


void initialize(char *send_data, char *recv_data, char *send_dl, char *recv_dl, char *dt)
{
    fps = fopen(send_data, "rb");
    if(!fps){
        printf("Open file %s to read error!\n", send_data);
        exit(1);
    }
    fseek(fps,0L,SEEK_END);
    fps_length = ftell(fps);
    fseek(fps,0L,SEEK_SET);

    fpr = fopen(recv_data, "wb");
    if(!fpr){
        printf("Open file %s to write error!\n", recv_data);
        exit(1);
    }

    strcpy(PHYSICAL_DATA_LINK_FILE_WRITE, send_dl);
    strcpy(PHYSICAL_DATA_LINK_FILE_READ, recv_dl);

    delay_time = atoi(dt);			/* this is microsecond */
    init_timer_value =  ((((float)delay_time) / 1000.0) * 17.2) * 2;
    /*init_timer_value 設置為兩倍的傳輸時間!!*/

    /* at first, the physical link is idle */
    unlink(PHYSICAL_DATA_LINK_FILE_WRITE);
    unlink(PHYSICAL_DATA_LINK_FILE_READ);

    /* save the old interrupt vector */
    oldhandler = getvect(INTR);

    /* install the new interrupt handler */
    setvect(INTR, handler);

    NextFrameToSend = 0;
    FrameExpected = 0;
    PacketLength = 0;
    waiting = false;
    network_layer_flag = true;
}

void cleanup()
{
    fclose(fps);
    fclose(fpr);

    /* when exit, set the state of physical link to idle */
    unlink(PHYSICAL_DATA_LINK_FILE_WRITE);
    unlink(PHYSICAL_DATA_LINK_FILE_READ);

    /* reset the old interrupt handler */
    setvect(INTR, oldhandler);
}


void start_timer(void)
{
    timer_count = init_timer_value;
    timer_run_flag = true;
}

void stop_timer(void)
{
    timer_run_flag = false;
}

int check_timer_expire(void)
{
    if((timer_count <= 0) && (timer_run_flag))
        return 1;
    else
        return 0;
}

void enable_network_layer(void){
    network_layer_flag = true;
}

void disable_network_layer(void){
    network_layer_flag = false;
}

void get_packet_from_network(packet *buffer, int *PacketLength)
{
    (*buffer) = (packet)fgetc(fps);
    (*PacketLength) = sizeof(packet);
}

void put_packet_to_network(packet pk)
{
    fputc((int)pk, fpr);
    fflush(fpr);
}

void send_frame_to_physical(struct frame fr)
{
    FILE *fp;

    /* 二進位打開檔寫,如果檔原來有內容,將刪除原來的內容 */
    fp = fopen(PHYSICAL_DATA_LINK_FILE_WRITE, "wb");
    if(!fp)
    {
        printf("Open data link file %s to write error!\n", PHYSICAL_DATA_LINK_FILE_WRITE);
        return;
    }
    fwrite(&fr, sizeof(struct frame),1, fp);
    fclose(fp);
}

void get_frame_from_physical(struct frame *fr)
{
    FILE *fp;

    /* 設置幀為無效 */
    fr->seq = -255;
    fr->ack = -255;

    fp = fopen(PHYSICAL_DATA_LINK_FILE_READ, "rb");
    if(!fp)
    {
        printf("Open data link file %s to read error!\n", PHYSICAL_DATA_LINK_FILE_READ);
        return;
    }
    fread(fr, sizeof(struct frame),1, fp);
    fclose(fp);

    /* this frame has been read, the file will be unlink */
    unlink(PHYSICAL_DATA_LINK_FILE_READ);
}

enum protocol_event get_event_from_physical()
{
#define	FILE_EXIST_FLAG	0
#define	FILE_READ_FLAG	4

    if(access(PHYSICAL_DATA_LINK_FILE_READ, FILE_READ_FLAG) == 0)
        return	FRAME_ARRIVAL;
    else
        return NO_EVENT;
}

int channel_idle(void)
{
    return true;		/* 認為物理通道總是空閒 */
}

enum protocol_event get_event_from_timer()
{
    if(check_timer_expire())
    {
        stop_timer();
        return TIME_OUT;
    }
    else
        return NO_EVENT;
}

/* Main protocol service routine */
void stop_wait_protocol_datalink(int event)
{
    struct frame send_frame, recv_frame, ack_frame;
    int PacketLength;

    switch(event)
    {
    case PACKET_READY :
        /* a packet has arrived from the network layer */
        get_packet_from_network(&buffer, &PacketLength);
        send_frame.info = buffer;		/* place packet in frame */
        send_frame.seq = NextFrameToSend;

        /* piggyback acknowledge of last frame received */
        send_frame.ack = 1-FrameExpected;
        if(channel_idle())
        {
            send_frame_to_physical(send_frame); /* send it to physical layer */
            start_timer();
            printf("Send DATA frame {packet = '%c', seq = %d, ack = %d} to physical\n", send_frame.info, send_frame.seq, send_frame.ack);
            waiting = false;
        }
        else
            waiting = true;

        disable_network_layer();
        break;

    case FRAME_ARRIVAL :
        /* a frame has arrived from the physical layer */
        get_frame_from_physical(&recv_frame);		/* get the frame */
        printf("Get a frame {packet = '%c', seq = %d, ack = %d} from physical\n", recv_frame.info, recv_frame.seq, recv_frame.ack);
        /* check that it is the one that is expected */
        if (recv_frame.seq == FrameExpected)	/* 有效幀到達,送到網路層 */
        {
            put_packet_to_network(recv_frame.info);	/* valid frame */
            printf("Put a packet to network {packet = %c}............\n", recv_frame.info);
            FrameExpected = 1-FrameExpected;

            /* 發送確認幀 */
            ack_frame.info = '\0';
            ack_frame.seq = -1;
            ack_frame.ack = recv_frame.seq;		/* 確認剛剛收到的一幀 */
            if(channel_idle())
            {
                send_frame_to_physical(ack_frame); /* send it to physical layer */
                printf("Send ACK frame {seq = %d, ack = %d}\n", ack_frame.seq, ack_frame.ack);
            }
        }
        if(recv_frame.ack == NextFrameToSend) /* acknowledgment has arrived,確認到達,可以發送下一幀 */
        {
            stop_timer();		/* 停止重發計時器 */

            enable_network_layer();
            NextFrameToSend = 1-NextFrameToSend;
        }
        break;

    case TIME_OUT :
        /* a frame has not been ACKed in time, */
        /* so re-send the outstanding frame */
        send_frame.info = buffer;
        send_frame.seq = NextFrameToSend;
        send_frame.ack = 1-FrameExpected;
        send_frame_to_physical(send_frame);
        start_timer();
        printf("Send DATA frame {packet = '%c', seq = %d, ack = %d) to physical\n", send_frame.info, send_frame.seq, send_frame.ack);
        break;

    case ChannelIdle:
        if ( waiting )
        {
            send_frame.info = buffer;
            send_frame.seq = NextFrameToSend;
            send_frame.ack = 1-FrameExpected;
            send_frame_to_physical(send_frame); /* send it to physical layer */
            start_timer();
            waiting = false;
        }
        break;
    case CheckSumError :	/* ignored */
        break;
    }
}

enum protocol_event get_event_from_network()
{
    if(!network_layer_flag)
        return NO_EVENT;

    if(ftell(fps) < fps_length)
        return PACKET_READY;
    else
        return NO_EVENT;

}

/*
	arg1	network send data (send file name)
	arg2	network receive data (receive file name)
*/
int main(int argc, char *argv[]){

    enum protocol_event event;
    char ev[20];
    unsigned int count;

    if(argc != 6)
    {
        printf("Usage: %s send_data recv_data send_dl  recv_dl delay_time", argv[0]);
        exit(0);
    }

    initialize(argv[1], argv[2], argv[3], argv[4], argv[5]);

    count = 1;
    printf("Protocol begin, any key to exit!\n\n");
    while(true)
    {
        printf("%d\n", count++);

        event = get_event_from_network();
        printf("Event from network = %s\n", event_string(event, ev));
        stop_wait_protocol_datalink(event);

        event = get_event_from_physical();
        printf("Event from physical = %s\n", event_string(event, ev));
        stop_wait_protocol_datalink(event);

        event = get_event_from_timer();
        printf("Event from timer = %s, timer_count = %d\n", event_string(event, ev), timer_count);
        stop_wait_protocol_datalink(event);

        delay(delay_time);

        if(kbhit())	break;
    }

    cleanup();

    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -