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

📄 tcp.c

📁 很好的网络编程协议源码
💻 C
字号:
/*
+FHDR------------------------------------------------------------------
Copyright (c),
Tony Yang –51,AVR,ARM firmware developer  
Contact:qq 292942278  e-mail:tony_yang123@sina.com.cn

Abstract:
$Id: tcp.c,v 1.10 2006/12/31 16:05:32 tony Exp $
-FHDR-------------------------------------------------------------------
*/ 
#include "config.h"
#include "tcp_ip_cfg.h"
#include "hardware.h"
#include "ethernet.h"
#include "uart0\uart0.h"
#include "icmp.h"
#include "arp.h"
#include "udp.h"
#include "ip.h"
#include "socket.h"

SOCKET TCP_Socket[MAX_TCP_LINKS];

/*本地TCP监听端口表*/
u16 TCP_PORT_Listening[MAX_TCP_Listening_Ports];
/*本地端口分配表*/
u16 Local_PORT_Pool[MAX_Local_PORT_Pool_SIZE];

struct TCP_Header *TCP_Header;

/****************************************************************************
* 名称:CHECK_Port_Can_be_Used()
* 功能:检查一个端口是否可用?
* 入口:PORT_NUM--端口号
* 出口: SUCC-可以使用;FAIL-禁止使用
****************************************************************************/
u8 CHECK_Port_Can_be_Used(u16 PORT_MUN)
{
  u16 i;
  for(i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
  {
    if(Local_PORT_Pool[i] == PORT_MUN)
      return(FAIL);
  }

  return(SUCC);
}


/****************************************************************************
* 名称:Free_a_LOCAL_Port(u16 PORT_MUN)
* 功能:释放的一个本地端口
* 入口:PORT_NUM--端口号
* 出口: SUCC-释放成功;FAIL-端口可用,无需释放
****************************************************************************/
u8 Free_a_LOCAL_Port(u16 PORT_MUN)
{
  u16 i;
  for(i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
  {
    if(Local_PORT_Pool[i] == PORT_MUN)
      {
        Local_PORT_Pool[i] = 0;
        return(SUCC);
      
      }
  }

  return(FAIL);

}
/****************************************************************************
* 名称:Allocate_A_LOCAL_Port()
* 功能:为客户端分配一个本地端口,用于连接至服务器
* 入口:无
* 出口:  0xffff-分配错误,正常为分配的端口号
****************************************************************************/

u16 Allocate_A_LOCAL_Port(void)
{
  u16 i,j;
  for(i = 0x410;i < (0x410 + MAX_Local_PORT_Pool_SIZE);i++)
  {
     if(CHECK_Port_Can_be_Used(i) == SUCC)
     {
         /*寻找一个空位,把PORT i写到本地端口分配表*/
         for(j = 0;j < MAX_Local_PORT_Pool_SIZE;j++)
           if(Local_PORT_Pool[j] == 0)
           {
                Local_PORT_Pool[j] = i;
                break;
           }
         if(j >= MAX_Local_PORT_Pool_SIZE)
            return(0xffff);
         else
            return(i);
     }
  }
  return(0xffff);
}

/****************************************************************************
* 名称:TCP_initial
* 功能:检查端口是否工作为监听状态?
* 入口:PortNUM-端口号
* 出口: SUCC FAIL
****************************************************************************/
u8 TCP_check_port_listening(u16 PortNUM)
{
   u16 i;
  for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
    if(TCP_PORT_Listening[i] == PortNUM)
    { 
      return(SUCC);
    }
  return(FAIL); 
}

/****************************************************************************
* 名称:enable_a_port_listen
* 功能:触发一个端口工作为监听状态?
* 入口:PortNUM-端口号
* 出口: SUCC FAIL
****************************************************************************/
u8 TCP_enable_a_port_listen(u16 PortNUM)
{
  u16 i;
  if(TCP_check_port_listening(PortNUM) == SUCC)
        return(FAIL);
  for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
    if(TCP_PORT_Listening[i] == 0)
    { 
      TCP_PORT_Listening[i] = PortNUM;
      return(SUCC);
    }
  return(FAIL);

}
/****************************************************************************
* 名称:TCP_Seek_4_elements
* 功能:查找四元组,一个四无组表示一个服务器与客户器连接
* 入口:pkt-TCP数据报的首地址,
*       index-UDP_Socket的索引
*       IP-源/目的首地址
* 出口: 无
****************************************************************************/
u8 TCP_Seek_4_elements(u8 * pkt,u16 * index,u8 *IP)
{
   u16 i,j,flag;
  
  for(i = 0 ;i < MAX_TCP_LINKS ;i++)
  {
    if(!TCP_Socket[i].EN)
       continue;
    /*检查PKT的源端口*/
    if(pkt[0] != TCP_Socket[i].DEST_Port[1] || pkt[1] != TCP_Socket[i].DEST_Port[0])
        continue;
    if(pkt[2] != TCP_Socket[i].SRC_Port[1] || pkt[3] != TCP_Socket[i].SRC_Port[0])
        continue;
    /*检查PKT的目的地址*/
    flag = SUCC;
    for(j = 0;j < 4;j++)
    {
      if(IP[j] != TCP_Socket[i].DEST_IP_Address[j] )
         {
            flag = FAIL;
            break; 
         }
    }  
   if(flag == SUCC)
     {
       for(j = 0;j < 4;j++)
       {
          if(IP[j+4] != TCP_Socket[i].SRC_IP_Address[j] )
           {
            flag = FAIL;
            break; 
           }
       }
       if(flag == SUCC)
       { 
         *index = i; 
         return(SUCC);
       }
     
       
     }
  }
  return(FAIL);
}
/****************************************************************************
* 名称:TCP_Write_4_element
* 功能:写一个四元组,表示一个服务器与客户器连接
* 入口:pkt-TCP数据报的首地址,
*       index-UDP_Socket的索引
*       IP-源/目的首地址
* 出口: 无
****************************************************************************/
void TCP_Write_4_element(u8 * pkt,u16 index,u8 *IP)
{
  u16 i;
   TCP_Socket[index].EN = 1;
  for(i = 0;i < 4;i++)
  {
   TCP_Socket[index].DEST_IP_Address[i] = IP[i];
   TCP_Socket[index].SRC_IP_Address[i] = IP[4+i];
  }
  
     TCP_Socket[index].DEST_Port[0] = pkt[1];
     TCP_Socket[index].DEST_Port[1] = pkt[0];
     
     
     TCP_Socket[index].SRC_Port [0] = pkt[3];
     TCP_Socket[index].SRC_Port [1] = pkt[2];

     TCP_Socket[index].SRC_SN[0] = pkt[11];
     TCP_Socket[index].SRC_SN[1] = pkt[10];
     TCP_Socket[index].SRC_SN[2] = pkt[9];
     TCP_Socket[index].SRC_SN[3] = pkt[8];

     TCP_Socket[index].DEST_SN[0] = pkt[7];
     TCP_Socket[index].DEST_SN[1] = pkt[6];
     TCP_Socket[index].DEST_SN[2] = pkt[5];
     TCP_Socket[index].DEST_SN[3] = pkt[4];
      

     TCP_Socket[index].SRC_WIN[0] = MAX_TCP_UDP_DATA_link_buf_len >> 8;
     TCP_Socket[index].SRC_WIN[1] = MAX_TCP_UDP_DATA_link_buf_len & 0xff;
     TCP_Socket[index].DEST_WIN[0] = pkt[15];
     TCP_Socket[index].DEST_WIN[1] = pkt[14];


  
  
}
/****************************************************************************
* 名称:UDP_initial
* 功能:初始化TCP模块
* 入口:无 
* 出口: 无
****************************************************************************/
void TCP_initial(void)
{
  u16 i;
  u8 j;
  for(i = 0;i < MAX_TCP_LINKS;i++)
  {
    TCP_Socket[i].DEST_Port[0] = 0;
    TCP_Socket[i].DEST_Port[1] = 0;
    TCP_Socket[i].SRC_Port[0] = 0;
    TCP_Socket[i].SRC_Port[1] = 0;
    for(j = 0;j < 4;j++)
    {
      TCP_Socket[i].DEST_IP_Address[j] =0x0;
      TCP_Socket[i].SRC_IP_Address[j] = 0x0;
    }
    TCP_Socket[i].Queue_Rear = 0;
    TCP_Socket[i].Queue_Front = 0;
    TCP_Socket[i].Queue_Full = 0;
    TCP_Socket[i].EN = 0;
    
    
    TCP_Socket[i].SRC_SN[0]  = 0x0;
    TCP_Socket[i].SRC_SN[1]  = 0x0;
    TCP_Socket[i].SRC_SN[2]  = 0x43;
    TCP_Socket[i].SRC_SN[3]  = 0x21;
    TCP_Socket[i].DEST_SN[0] = 0; 
    TCP_Socket[i].DEST_SN[1] = 0;
    TCP_Socket[i].DEST_SN[2] = 0;
    TCP_Socket[i].DEST_SN[3] = 0;
      
    TCP_Socket[i].SRC_WIN[0] = MAX_TCP_UDP_DATA_link_buf_len >> 8;
    TCP_Socket[i].SRC_WIN[1] = MAX_TCP_UDP_DATA_link_buf_len & 0xff;
    
    TCP_Socket[i].DEST_WIN[0] = 0;
    TCP_Socket[i].DEST_WIN[1] = 0;
    TCP_Socket[i].status = Closed;
    TCP_Socket[i].ACK_Unsended = 0;;
    TCP_Socket[i].last_pkt_len = 0;
    TCP_Socket[i].timeout_ack = 0;
    TCP_Socket[i].type = NOT_Listening;
  }
  for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
    TCP_PORT_Listening[i] = 0;
  for( i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
    Local_PORT_Pool[i] = 0;
   

}
/****************************************************************************
* 名称: Send_TCP_PKT
* 功能:发送一个TCP数据报
* 入口:TxdData--需发送数据的指针,
* dest_ip_add:目的IP地址
* 出口: 无
****************************************************************************/
void Send_TCP_PKT(struct _pkst *TxdData,u8 *dest_ip_add)
{
  Send_IP_PKT(TxdData,dest_ip_add,TCP);


}

/****************************************************************************
* 名称: bigEND_u32_add_1
* 功能:对大端模式的32位整数据加1
* 入口:data1-数据的首地址
* 
* 出口: 无
****************************************************************************/
void bigEND_u32_add_1(u8 * data1)
{
     if(data1[3] !=0xff)
     {
       data1[3]++;
     }
     else if(data1[2] != 0xff)
           { data1[3] = 0;
             data1[2]++;
           }
           else if(data1[1] != 0xff)
           {data1[2] = 0;
            data1[1]++;
           }
           else if(data1[0] != 0xff)
           { data1[1] = 0;
             data1[0] ++;
           }
           else
             data1[0] = 0;
        
}

/****************************************************************************
* 名称: littleEND_u32_add_1
* 功能:对小端模式的两个32位整数据相加
* 入口:data1-数据的首地址
* 
* 出口: 无
****************************************************************************/
void littleEND_u32_add(u8 * data1,u8 * data2)
{
 s8 i;
 u16 temp,temp1;
 temp1 = 0;
 for(i = 0;i < 4;i++)
 { 
   temp = data1[i] + data2[i] + temp1;
   if(temp > 255)
     temp1 = 1;
   else
     temp1 = 0;
   data1[i] = temp & 0xff;  
 
 
 }

        
}
/****************************************************************************
* 名称:Send_TCP_ACK()
* 功能:发送ACK数据报

⌨️ 快捷键说明

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