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

📄 源程序清单.c

📁 我大三做的通信与接口的课程设计,成绩是优,里面含有完整课程设计报告,实现了聊天,和文件传送,可传二进制文件,程序简单易懂
💻 C
字号:
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <bios.h>
#include <string.h>
#define SIZE 32768


void InitData(void);    /*端口初始化*/
void Initscreen(void);  /*屏幕初始化*/
void Send(void);        /*发送字符*/
void SandRchar(void);   /*发送并接收字符*/
void Sdfile(void);      /*发送文件函数*/
void Receive(void);     /*接收字符函数*/
void Rcfile(void);      /*接收文件函数*/
void recv_wait();       /*接收等待函数*/
void send_wait();       /*发送等待函数*/
void interrupt far char_proc(void);  /*中断函数*/
void interrupt ( *mode)(void);       /*中断向量*/

char filename[20];
int com1;
int flag=1;
long ii;
unsigned char state;        /*定义几个全局变量*/

typedef struct
{
    char *base;
    int front;
    int rear;
}                           /*定义队列*/
SqQueue;

int InitQueue(SqQueue *Q)   /*构造一个空队列Q*/
{
    Q->base=(char *) malloc(SIZE+1 *sizeof(char));
    if(!Q->base) exit(-2);
    Q->front=Q->rear=0;
    return 1;
}

int QueueLength(SqQueue *Q) /*返回Q的元素个数,即队列的长度*/
{
    return (Q->rear-Q->front+SIZE)%SIZE;
}

int EnQueue(SqQueue *Q,char e)/*插入元素e为Q的新的队尾元素*/
{
    if((Q->rear+1)%SIZE==Q->front) return 0;
    Q->base[Q->rear]=e;
    Q->rear=(Q->rear+1)%SIZE;
    return 1;
}

int DeQueue(SqQueue *Q ,char *e)/*若队列不空,则删除Q的队头元素,用e返回其值,并返回1;否则返回0 */
{
    if(Q->front==Q->rear) return 0;
    *e=Q->base[Q->front];
    Q->front=(Q->front+1)%SIZE;
    return 1;
}

void CrQueue(SqQueue *Q)/*清空队列*/
{
    Q->front=Q->rear=0;  
}


union
{
    char c[sizeof(long)];
        long len;
}
scnt,rcnt;              /*用联合体表示文件的长度*/

SqQueue Q;              /*创建一个全局的队列变量*/

/************初始化com1端口************/

void InitData()
{
   unsigned char i,j;
   com1=0x3f8;
   InitQueue(&Q);      /*初始化队列*/
   j=inportb(com1+3);  /*取线路控制寄存器的值*/
   j=j|0x80;           /*使DLAB=1,对除数寄存器置初值*/
   outportb(com1+3,j);
   outportb(com1,0x01);/*写除数寄存器低八位*/
   outportb(com1+1,0); /*写除数寄存器高八位*/
   j=inportb(com1+3);
   j=j&0x7f;           /*使DLAB=0*/
   outportb(com1+3,j);
   outportb(com1+3,0x03);
}

/************发送字符************/

void Send()
{
   unsigned char at;
   char c;
   at=inportb(com1+5);
   at=at&0x20;
   if(at) if(DeQueue(&Q,&c)) outportb(com1,c);
}

/**************发送等待*************/

void send_wait()
{
    state=inportb(com1+5);
    state=state&0x20;
    while(!state)
    {
        state=inportb(com1+5);
        state=state&0x20;
    }
}

/***********接收字符函数*************/

void Receive()
{
   char c;
   state=inportb(com1+5);
   state=state&0x01;
   if(state) 
   {
   c=inportb(com1);
   if(c=='\r')
   printf("\n\n    ");
   else
   {
   textcolor(60);
   cprintf("%c",c);
   }
   }
}


/**************接收等待****************/

void recv_wait()
{
    state=inportb(com1+5);
    state=state&0x01;
    while(!state)
    {
        state=inportb(com1+5);
        state=state&0x01;
    }
}

/************发送或接收字符函数***************/

void SandRchar()
{
  int i;
  char c;
  CrQueue(&Q);
  clrscr();
  printf("\n\n         ------------------------------\n");
  printf("              press ESC to be back \n");
  printf("         ------------------------------\n\n");
  printf("==================================================\n\n");
  printf("    ");
  while(1)
  {
     while(!kbhit())       /*没按键则一直发送,接收*/
     {
        Send();
        Receive();
     }
     c=getch();
     if(c=='\x1B') break;  /*按ESC则退出*/
     if(c=='\r')           /*特殊处理回车键*/
     {
     printf("\n\n    ");
     EnQueue(&Q,c);
     }
     else
     {                     /*有按键就进队列,显示*/
     EnQueue(&Q,c);
     textcolor(10);
     cprintf("%c",c);
     }
  }
}

/***************计算文件大小***************/

long get_file_size(FILE *temp_fp)  
{
    long temp_file_len;
    fseek(temp_fp,0,SEEK_END);    /*文件指针移到文件未尾*/
    temp_file_len=ftell(temp_fp); /*文件指针未尾的位置,即文件长度*/
    fseek(temp_fp,0,SEEK_SET);    /*文件指针回到文件开头*/
    return temp_file_len;
}

/***************发送文件***************/

void Sdfile()
{
  FILE *fp;
  unsigned char ch;
  int i,done,j;
  long t,t1;
  float st;
  unsigned long size;
  done=j=0;
  CrQueue(&Q);
  while(done<4)
  {
    printf("    input file name you want to send:  ");
    scanf("%s",filename);                   
    if((fp=fopen(filename,"rb"))==NULL)/*以二进制方式打开文件*/
    {
            printf("\n    file open error! try again..... \n");
            done++;
    }
    else done=5;
  }
   if(done==4)
        {
           printf("\n    file open error too much time!\n");
           getch();
           return;
        }

  scnt.len=get_file_size(fp); /*获得文件长度*/

  send_wait();
  outportb(com1,'<');         /*发送开始字符*/

  for(i=0;i<sizeof(long);i++) /*发送文件长度大小给接收方*/
  {
       send_wait();
       outportb(com1,scnt.c[i]);
  }
  printf("\n\n    Link.......wait......    \n");
  recv_wait();                /*等待回应*/
  state=inportb(com1);
  if(state!='>')
  {
    printf("\n    connect fail\n"); /*连接失败*/
    return;
   }
  printf("\n    connect succeed!\n");
  size = scnt.len;
  printf("\n    The size of the file is %ld bytes;",size);
  printf("\n\n    Now Sending....... 00%");
  t=clock();

/**********发送文件,每发4K字节发一个效验和字节*********/

  while(size>SIZE)
  {
   for(ii=0;ii<SIZE;ii++)
   {
     ch=fgetc(fp);
     EnQueue(&Q,ch);
     Send();
   }
  while(QueueLength(&Q)) Send();  /*继续发队列中剩余的*/
  size-=SIZE;
  j++;

/***********发送效检和字节***********/
  
  send_wait();
  outportb(com1,'?');
  recv_wait();
  ch=inportb(com1);
  if(ch!='!')   /*if 对方发送回来提示效检字节错,则重发4K字节*/
    {
       fseek(fp,SIZE,SEEK_CUR);/*文件指针前移4K字节*/
       size+=SIZE;
       j--;
    }
  else {textcolor(10);cprintf("\b\b\b\b%3d%",100*j*SIZE/scnt.len);}  /*显示发送进度*/
   }

  while(size>0)   /*发送比4K小的字符*/
  {
      ch=fgetc(fp);
      size--;
      EnQueue(&Q,ch);
      Send();
  }
  while(QueueLength(&Q)) Send();
  t1=clock();
  textcolor(60);
  cprintf("\b\b\b\b100%");
  fclose(fp);  /*关闭文件*/
  st=(t1-t)/18.2;
  printf("\n\n    Send Complete!\n\n");
  printf("    Total use %5.3f s.\n\n",st);
  printf("    Total send %ld Bytes.\n\n",scnt.len);
  if(st>0)    /*防止除数为0的情况*/
  printf("    The rate is %5.3f Bytes/s.\n",scnt.len/st);
  else printf("    The rate is 115.2 KBytes/s.\n");
  getch();
  }

/***********中断服务程序***********/

void interrupt far char_proc()
{
   state=inportb(com1);
   if(state=='<')
   Rcfile();
   flag=0;
   outportb(0x20,0x20);
}

/***********初始化中断***********/

void init_pt()
{   char t;
    mode = getvect(0x0c);/*获取中断处理程序的入口地址*/
    disable(); /*关中断*/
    outportb(0x3fc,0x08|0x0b); /*out2,dtr,rts信号有效*/        
    outportb(0x3f9,0x01); /*允许接收中断*/
    t = inportb(0x21);
    t = t&0xef; /* t & 1110 1111 ,开放IRQ4,即com1的中断请求*/
    outportb(0x21,t);
    setvect(0x0c,char_proc);
    enable(); /*开中断*/
    while(flag){}
    outportb(0x3f9,0);                                               
    t = inportb(0x21);
    t = t|0x10; /* t | 0001 0000 ,关IRQ4,即com1的中断请求*/
    outportb(0x21,t);
    setvect(0x0c,mode);/*为指定的中断向量设置中断服务函数,interruptno 中断向量,isr中断函数,该函数应使用interrupt关键字声明*/
    flag=1;
}

/**************接收文件***************/

void Rcfile()
{
  int done,i,j;
  FILE *fp;
  long sizec;  /*文件的长度*/
  unsigned char ch;
  done=i=j=0;
  CrQueue(&Q);

  for(j=0;j<4;j++)   /*接收文件长度*/
    {
         recv_wait();
         rcnt.c[j]=inportb(com1);
    }

  sizec=rcnt.len;

  while(!done)
  {
    printf("\n    creat the file  to receive and save  :   ");
    scanf("%s",filename);
    if((fp=fopen(filename,"wb"))==NULL)
        {  
                printf("    file already exists !\n");
        }
        else done=1;
  }
  send_wait();
  outportb(com1,'>');
  printf("\n    Now Receiving......... 00%");   /*接收进度条*/
 
  while(rcnt.len>SIZE)      /*每次接收4K*/
  {
    for(ii=0;ii<SIZE;ii++)  /*接收4K,存入队列中*/
    {
        recv_wait();
        ch=inportb(com1);
        EnQueue(&Q,ch);
    }
  recv_wait();
  state=inportb(com1);
  if(state=='?')            /*接收正确,把队列中的字符写入文件*/
    {
    for(ii=0;ii<SIZE;ii++)
        {
            DeQueue(&Q,&ch);
            fputc(ch,fp);
        }
    rcnt.len-=SIZE;         /*剩余的字节数*/
    send_wait();
    outportb(com1,'!');     /*回答发送方收接正确,继续发*/
    i++;
    textcolor(10);
    cprintf("\b\b\b\b%3d%",100*i*SIZE/sizec);   /*接收进度条*/
    }
   else
     {
            CrQueue(&Q);    /*接收错误,清空队列重收*/
            send_wait();
            outportb(com1,0x00);
     }
  }
  if(rcnt.len>0)            /*接收剩余的字符*/
   {
      for(ii=0;ii<rcnt.len;ii++)
         {
           recv_wait();
           ch=inportb(com1);
           EnQueue(&Q,ch);
         }
      for(ii=0;ii<rcnt.len;ii++)
         {
            DeQueue(&Q,&ch); 
            fputc(ch,fp);
         }
    }
   fclose(fp);    /*关闭文件*/
   textcolor(60);
   cprintf("\b\b\b\b100%");
   printf("\n\n    Receive Complete!\n\n");
   printf("\n\n    Total send %ld Bytes.",sizec);
   getch();
  }

/*****************初始化屏幕*****************/

void  Initscreen()
{  
   clrscr();     /*清屏*/
   printf("\n");
   printf("\n            ------------------------------------------------"); 
   printf("\n                choice   1:    send      file;        "); 
   printf("\n                choice   2:    receive   file;        ");
   printf("\n                choice   3:    send      receive  char; ");
   printf("\n                choice   0:    quit      to    window;");
   printf("\n            -------------------------------------------------\n");   
 }

/***************主函数*************/

main()
{
  char ch;
  InitData();
  while(1)
  {
  Initscreen();
  ch=getch();
  while(ch!='1'&&ch!='2'&&ch!='3'&&ch!='0')
  { 
    printf("\n    ERROR! Please Choose Again\n\n");
    ch=getch();
  }
  if(ch=='1')  {printf("\n  ------------SEND FILE PART------------ \n\n");
                 Sdfile();}
  else if(ch=='2') {printf("\n  ------------RECEIVE FILE PART------------ \n\n");
                 init_pt();}
  else if(ch=='3') {printf("\n  ------------TALKING PART------------- \n\n");
                 SandRchar();}
  else if(ch=='0') exit(0);
  else if(ch!='1'&&ch!='2'&&ch!='3'&&ch!='0')
  ch=getch();
  }
}

⌨️ 快捷键说明

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