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

📄 tcpserver.c

📁 用AVR单片机和RTL8019实现TCP/IP协议.支持ARP,PING,UDP,TCP,HTML网页显示等功能.
💻 C
📖 第 1 页 / 共 2 页
字号:
   else if( (tcp_remote_dsz==0)&&(tcp_remote_flag!=0)&&(tcp_remote_flag!=TCP_SYN)) 
  {
     TCP_MY_SEQ=tcp_remote_ack;                      // 处于建立过程的非第一次数据回复
     TCP_MY_ACK=tcp_remote_seq+1;                    // ACK序号值加1
  }
   else if(tcp_remote_dsz!=0) 
  {
     TCP_MY_SEQ=tcp_remote_ack;                      // 处于已经建立后数据回复
     TCP_MY_ACK=tcp_remote_seq+tcp_remote_dsz;       // ACK序号值加收到的数据长度 
  }
  
 //***以下代码根据目前状态及当前数据,判断执行何种操作***
 //A. 通信复位 
 //B. 已建立连接状态下进行数据接收处理
 //C. 进入TCP连接建立过程
 //根据状态判断选择执行内容
 if ( (tcp_remote_flag&TCP_RST)!=0x00 )
   {
    //debuG
	uart_send('R');
	uart_send('S');
	uart_send('T');
	uart_send(' ');
	//debuG
    TCP_STATE=TCP_LISTEN;                            // 如果收到复位标志,则进入TCP_LISTEN状态
	tcp_init_sw(1);
   }
 else if( (TCP_STATE==TCP_ESTABLISHED)&&((tcp_remote_flag&TCP_FIN)==0)&&(tcp_remote_flag!=TCP_SYN ))
   {
    //debuG
	uart_send('D');
	uart_send('A');
	uart_send('T');
    uart_send('S');
	uart_send(0x0d);	
	uart_send(0x0a);	
    uart_send(0x0d);	
	uart_send(0x0a);	
	//debuG
	// 这种条件表示收到实质性的数据

    tcp_port_handle();                               // 如果已建立连接,且收到的不是连接终止信号
                                                     // 则进行有效接收数据处理 。。。
    //debuG
	uart_send(0x0d);	
	uart_send(0x0a);	
	uart_send('D');
	uart_send('A');
	uart_send('T');
    uart_send('E');
	uart_send(0x0d);	
	uart_send(0x0a);	
    uart_send(0x0d);	
	uart_send(0x0a);	
	//debuG
   }
 else 
    tcp_state_machine(tcp_remote_flag);              // 调用TCP STATE转换程序处理
}

//**********************************
//*  TCP SERVER数据发送
//**********************************
void tcpserver_send_data(unsigned int data_length,unsigned char hdr_sz,unsigned char flag)
{
 unsigned char temp0;
 unsigned char temp1;
 unsigned int  temp2;
 unsigned int  temp3;
 unsigned long temp4;
 // 1.ETHERNET部分数据构建,只对MAC进行处理,FRAME TYPE不边
 //   a.对已收到的ETHERNET数据包目标NAC地址和源MAC地址相互交换
 for(temp0=0;temp0<6;temp0++)
 {
  temp1=read_62256(SRCMAC0+temp0);
  write_62256(DESMAC0+temp0,temp1);
 }
 for(temp0=0;temp0<6;temp0++)
  write_62256(SRCMAC0+temp0,SYSMAC[temp0]); 
  
 // 2.TCP部分数据构件,大部分参数保存在全局变量中
 //   a.TCP端口源端口和目的端口互换
 temp0=read_62256(TCP_SRC_PORT);
 temp1=read_62256(TCP_DES_PORT);
 write_62256(TCP_SRC_PORT,temp1);
 write_62256(TCP_DES_PORT,temp0);
 temp0=read_62256(TCP_SRC_PORT+1);
 temp1=read_62256(TCP_DES_PORT+1);
 write_62256(TCP_SRC_PORT+1,temp1);
 write_62256(TCP_DES_PORT+1,temp0);
 //   b.设置数据顺序号
 write_62256(TCP_SEQ_NO,(TCP_MY_SEQ>>24)&0x000000FF);
 write_62256(TCP_SEQ_NO+1,(TCP_MY_SEQ>>16)&0x000000FF);
 write_62256(TCP_SEQ_NO+2,(TCP_MY_SEQ>>8)&0x000000FF);
 write_62256(TCP_SEQ_NO+3,TCP_MY_SEQ&0x000000FF);
 //   c.设置数据确认号
 write_62256(TCP_ACK_NO,(TCP_MY_ACK>>24)&0x000000FF);
 write_62256(TCP_ACK_NO+1,(TCP_MY_ACK>>16)&0x000000FF);
 write_62256(TCP_ACK_NO+2,(TCP_MY_ACK>>8)&0x000000FF);
 write_62256(TCP_ACK_NO+3,TCP_MY_ACK&0x000000FF);
 //   d.设置TCP数据头长度
 write_62256(TCP_HDR_SZ,hdr_sz<<2);                // 20*4=80(0x50) /24*4=96(0x60)
 //   e.设置FLAG数值
 write_62256(TCP_FLAG,flag);                       // FLAG由上层程序制定
 //   f.设置TCP数据WINDOW SIZE
 write_62256(TCP_WIN_SZ,TCP_MY_MSS>>8);           // WINDOW SIZE与最大接收数相同
 write_62256(TCP_WIN_SZ+1,TCP_MY_MSS&0X00FF);    //
 //   g.设置CHECKSUM先置0
 write_62256(TCP_CSUM,0x00);                       // checksum先置0
 write_62256(TCP_CSUM+1,0x00);
 //   h.设置URGENT POINT置0
 write_62256(TCP_GUR_PT,0x00);                     // URGENT POINT置0
 write_62256(TCP_GUR_PT+1,0x00);
 //   i.如有OPTION设置(默认设置MSS),如没有跳过
 if(hdr_sz!=20)
 {
  write_62256(TCP_OPTION,2);                       // OPTION TYPE=2
  write_62256(TCP_OPTION+1,4);                     // OPTION LENGTH=4
  write_62256(TCP_OPTION+2,TCP_MY_MSS>>8);         // OPTION MSS高8位
  write_62256(TCP_OPTION+3,TCP_MY_MSS&0X00FF);     // OPTION MSS低8位
 }
 //  j.设置TCP数据包的数据内容,内容长度data_length(<=TCP_MAX_SEND)
 //    上层程序负责将数据写入
 //  k.TCP_CHECK_SUM计算
  temp3=data_length+hdr_sz;
  temp2=tcp_check_sum(temp3);                     // tcp checksum计算,数据头+数据
  write_62256(TCP_CSUM,temp2>>8);
  write_62256(TCP_CSUM+1,temp2&0x00FF);
  
 // 3.IP数据头构建,在原数据基础上修改,修改内容包括TOTAL LENGTH,ID
 //   a.修改IP头的TOTAL LENGTH数据
  temp3=data_length+hdr_sz+20;                    // TCP+IP总长度
  write_62256(IP_TOL_LEN,temp3>>8);
  write_62256(IP_TOL_LEN+1,temp3&0X00FF);
 //   c.修改IP头的16位ID
  temp2=read_62256(IP_ID_ADD);                    // IP头数据中ID标识区数据加1
  temp1=read_62256(IP_ID_ADD+1);
  temp2=(temp2<<8)+temp1;
  temp2=temp2-1;
  write_62256(IP_ID_ADD+1,temp2);
  write_62256(IP_ID_ADD,temp2>>8);
 //   d.IP头的16位head checksum置0 
 write_62256(IP_HDR_CSUM,0x00);                    // IP头CHECKSUM部分至0x0000
 write_62256(IP_HDR_CSUM+1,0x00);
 //   e.IP地址互换
 for(temp0=0;temp0<4;temp0++)                      // 设置目标IP地址
 {
  temp1=read_62256(IP_SRC_IP0+temp0);
  write_62256(IP_DES_IP0+temp0,temp1);
 }
 for(temp0=0;temp0<4;temp0++)
   write_62256(IP_SRC_IP0+temp0,SYSIP[temp0]);     //  设置本机IP地址
 //   f.修改IP的CHECKSUM
 temp2=ip_cal_csum();                              //  IP头chechsum计算
 write_62256(IP_HDR_CSUM+1,temp2);              
 write_62256(IP_HDR_CSUM,temp2>>8);
 
 //4.数据发送
 temp2=20+hdr_sz+data_length;                     // 注意了...,数据长度要大于46
 if(temp2<46)                                     // 不大于46怎么也调不出来
 {
   temp2=46-temp2;   
   for(temp0=0;temp0<temp2;temp0++)                             
       write_62256(TCP_SRC_PORT+hdr_sz+data_length+temp0,0x00);  // 不够的补上0
 }
 else temp2=0;
 sendpacket(data_length+hdr_sz+0x22+temp2);          //  发送数据
}

//************************************
//      TCP数据包头CHECKSUM
//************************************
unsigned int tcp_check_sum(unsigned int length)
{
 unsigned char temp;
 unsigned int i;
 unsigned long datah=0x00000000;
 unsigned int data=0x0000;
 //***TCP CHECK分为两部分,TCP和dumpheader***
 //1.以下对TCP数据段进行求和处理
 if( (length&0x0001)==0x0000 )                 // a1.偶数处理
 {
 for(i=0;i<length;i=i+2)
 {
  data=read_62256(i+TCP_SRC_PORT);             // 高位数值xxxxabcd
  datah=datah+(data<<8);                       // 形成数值xxxxabcdxxxx
  temp=read_62256(i+TCP_SRC_PORT+1);
  datah=datah+temp;
  //仔细研究一下为什么回出错??????????
  //datah=datah+read_62256(i+TCP_SRC_PORT+1);   // 形成数值xxxxabcdefgh
 }
  }
 else                                          // a2.奇数处理
 {
 for(i=0;i<(length-1);i=i+2)
 {
  data=read_62256(i+TCP_SRC_PORT);             // 高位数值xxxxabcd
  datah= datah+(data<<8);                      // 形成数值xxxxabcdxxxx
  temp=read_62256(i+TCP_SRC_PORT+1);
  datah=datah+temp;
  //datah=datah+read_62256(i+TCP_SRC_PORT+1);    // 形成数值xxxxabcdefgh
  }
  data=read_62256(length+TCP_SRC_PORT-1);     // 高位数值xxxxabcd
  datah=datah+(data<<8);                      // 形成数值xxxxabcdxxxx
  datah=datah+0x00;                           // 形成数值xxxxabcdefgh
  }
 //2.对dumpheader部分求和
 data=0x0000;
 for(i=0;i<8;i=i+2)                            // b.对源和目的IP地址求和
 {
  data=read_62256(i+IP_SRC_IP0);               // 高位数值xxxxabcd
  datah= datah+(data<<8);                      // 形成数值xxxxabcdxxxx
  temp=read_62256(i+IP_SRC_IP0+1);
  datah=datah+temp;                            // 形成数值xxxxabcdefgh
 }
  datah=datah+length;                          // c.加上TCP位长度,共有16位
  datah=datah+0x0006;                          // d.加上协议标志,仅有8位
  while( ( data=(datah>>16) )!=0x0000 )
  {
   datah=(datah&0x0000ffff)+data;
  }
  
  data=datah&0x0000ffff;
  data=0xFFFF-data;
 return data;
}

//**********************************
//*  TCP端口选择及数据处理
//**********************************
void tcp_port_handle(void)
{
 unsigned char data;
 unsigned int port;                           // tcp port
 port=read_62256(TCP_DES_PORT);               // xxab
 port=(port<<8);                              // abxx
 data=read_62256(TCP_DES_PORT+1);
 port=port+data;                              // abcd计算出TCP PORT的值
 if(port==80)                                 // http();      
{                                             // 执行具体应用程序
 http_handle();
}
}

⌨️ 快捷键说明

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