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

📄 tcp.c

📁 RTL8019以太网开发板资料
💻 C
📖 第 1 页 / 共 3 页
字号:
输出:         None
返回:         None
日期:         2004/02/04
*********************************************************************/
void tcp_Send(UWORK16 flags,  UWORK16 TCPHead_len, UWORK8 nr, UWORK8 *TData, UWORK16 TLen)
{
   ST_TCP_FORMAT *strTcp;
   UWORK8 destIP_buf[4];
   UWORK8 *TempD;
   TempD = TData; 
   strTcp = (ST_TCP_FORMAT *)&NetSend_buf[20];

  strTcp->usSourcePort = SourcePort;				//源端口
  strTcp->usDesPort = DesPort;			//目标端口,在接收TCP时已附值

  strTcp->ucSERIESNUM = StrConnection_buf[nr].ucSERIESNUM;	 //序号为0
  strTcp->ucTRUECODE = StrConnection_buf[nr].ucTRUECODE;	 //确认号为0

  memcpy(destIP_buf,(UWORK8 *)&StrConnection_buf[nr].ipaddr, 4);	//发送的目标IP地址在TCP接收中已附值

   strTcp->ucMOVENUM = (TCPHead_len << 10) | flags;		  //记算TCP的头长度及相关的标志位
   strTcp->ucWINDOWBIG = 1024;						  //设置窗口大小
   strTcp->ucTCPCHECK = 0;							  //先设置校验位为0
   strTcp->ucMUSGPOINT = 0;							  //紧急指针为0
   
   if (TCPHead_len == 24)							   //建立连接是的TCP的选项
   {
      memcpy(&strTcp->options[0], optionsRe_buf, 4);		   //把默认的TCP选择附值过去
   } 
   else if (TCPHead_len == 28)							   //如果发送的字节为28,那么多余的部分为TCP的很选项
   {
      memcpy(&strTcp->options[0], options_buf, 8);		   //把默认的TCP选择附值过去
   }
   memcpy((UWORK8 *)&NetSend_buf[(20 + TCPHead_len)], TData, TLen);		//把发送的数据传到发送缓存中 
   //下面是给IP打包头
    gstIphead.ucVerAndLen = 0x45;                       //版本号和长度,各占4位
    gstIphead.ucDs = 0;                        //区分服务
    gstIphead.usTotalLen = IP_HEAD_LEN + TCPHead_len + TLen;                        //头加后面的数据
    gstIphead.usID = ++LocalIpID;
    gstIphead.usSegOffset = 0;

    gstIphead.ucTTL = 0;										 // max hops
    gstIphead.ucprotocol = TCP;
    gstIphead.usCheckSum = TCPHead_len + TLen;                                   //在计算TCP的校验位时,TCP的长度要算两次,此时是借IP的校验位来做第二个TCP的长度
    memcpy(&gstIphead.ucDestIP[0],&IPDestAddress_buf[0],IP_LEN);          // 目的IP 
    memcpy(&gstIphead.ucSourceIP[0],&IPLocalAddress_buf[0],IP_LEN);                // 源IP    
    memcpy(&NetSend_buf[0],&gstIphead,20);										  //把IP的头传给发送缓存区
	strTcp->ucTCPCHECK = 0;
	strTcp->ucTCPCHECK = CheckSum((UWORK16 *)&NetSend_buf[8],TCPHead_len + TLen + 12);   // 20 = 12个字节伪头 + 8个字节UDP头 

    gstIphead.ucTTL = 0x20;                                                   //校验和计算完毕,重赋TTL值 
    memcpy(&MAC_Remote_buf[0],&gstaRevEthernet.ucaSourceNodID[0],MAC_LEN);    // 目的MAC 
//    memcpy((UWORK8 *)&MAC_Remote_buf[4],&gstaRevEthernet.ucaDestNodID[0],MAC_LEN);    // 目的MAC 
//	memcpy(&MAC_Remote_buf[0],&ArpCache_Buf[0].ucaMAC[0],MAC_LEN);          // 远程MAC */
	IpSend();
   // (Re)start TCP retransmit timer
    StrConnection_buf[nr].timer = TCP_TIMEOUT;
	StrConnection_buf[nr].HttpFlag = TCP_TDATA;
	StrConnection_buf[nr].inactivity = 0;
	StrConnection_buf[nr].ucRESERIESNUM = StrConnection_buf[nr].ucSERIESNUM;
	StrConnection_buf[nr].SendLen = TLen;
	StrConnection_buf[nr].ReSendNum = 3;
	memcpy((UWORK8 *)&StrConnection_buf[nr].query[0], (UWORK8 *)&NetSend_buf[20], TCPHead_len);
}

/*********************************************************************
函数名:       void SeriesToTcp(UWORK8 *pucAddr,UWORK16 usLen)
功能:         串口数据向TCP发送
输入:         None 
输出:         None
返回:         None
日期:         2004/02/04
*********************************************************************/
void tcp_ReSend(UWORK16 TLen, UWORK8 nr)
{
	memcpy((UWORK8 *)&NetSend_buf[20], (UWORK8 *)&StrConnection_buf[nr].query[0], 20);
   //下面是给IP打包头
    gstIphead.ucVerAndLen = 0x45;                       //版本号和长度,各占4位
    gstIphead.ucDs = 0;                        //区分服务
    gstIphead.usTotalLen = IP_HEAD_LEN + 20 + TLen;                        //头加后面的数据
    gstIphead.usID = ++LocalIpID;
    gstIphead.usSegOffset = 0;

    gstIphead.ucTTL = 0x20;										 // max hops
    gstIphead.ucprotocol = TCP;
//    memcpy((UWORK8 *)&MAC_Remote_buf[4],&gstaRevEthernet.ucaDestNodID[0],MAC_LEN);    // 目的MAC 
//	memcpy(&MAC_Remote_buf[0],&ArpCache_Buf[0].ucaMAC[0],MAC_LEN);          // 远程MAC */
	IpSend();
   // (Re)start TCP retransmit timer
    StrConnection_buf[nr].timer = TCP_TIMEOUT;
}
/*********************************************************************
函数名:       void SeriesToTcp(UWORK8 *pucAddr,UWORK16 usLen)
功能:         串口数据向TCP发送
输入:         None 
输出:         None
返回:         None
日期:         2004/02/04
*********************************************************************/
void TcpFromSeries(UWORK8 *pucAddr,UWORK16 usLen)
{
	UWORK8 p;
	for(p = 0; p < 5; p++)		   //发现在一次没有连接,则一个IP为0
	{
		if((StrConnection_buf[p].ipaddr != 0) && (StrConnection_buf[p].state == STATE_ESTABLISHED))		 //如果IP地址不是0,就表示有相关的连接
		{
			StrConnection_buf[p].state = STATE_SYN_SEND;		  //发送数据等待回复
			tcp_Send(FLG_PSH | FLG_ACK,  20, p, pucAddr, usLen);			
//			tcp_Send(FLG_RST,  20, p, pucAddr, usLen);			
		}
	}
}
	



//------------------------------------------------------------------------
// This handles incoming TCP messages and manages the TCP state machine
// Note - both the SYN and FIN flags consume a sequence number.
// See "TCP/IP Illustrated, Volume 1" Sect 18.6 for info on TCP states
// See "TCP/IP Illustrated, Volume 1" Sect 17.3 for info on flags
//------------------------------------------------------------------------
void TCPReceive(void)
{
   UWORK8 i, p, nr;
   UWORK16 result, header_len, data_len, len;
   ST_IP_HEAD_FORMAT StrIp;
   ST_TCP_FORMAT strTcp;
   UWORK16 sum, TcpFlag;		   //TcpFlag为TCP的标志位,是偏移量后6位
   UWORK32 RcvIPAdrr;				//接收的IP地址
   UWORK8 *pucTCPData;
   
    if(FALSE == gbHaveFragment)
    {                             // 没有分片的数据 
	   memcpy((UWORK8 *)&StrIp.ucVerAndLen, (UWORK8 *)&gstaRevEthernet.ucaPacket[0], 20);	  //读取IP头数据
       memcpy((UWORK8 *)&strTcp.usSourcePort, (UWORK8 *)&gstaRevEthernet.ucaPacket[20], 20);  //读取TCP头数据
	}
    else
    {                             // 分片的数据 
		memcpy((UWORK8 *)&StrIp.ucVerAndLen, (UWORK8 *)&gucaSegTemp[0], 20);	  //读取IP头数据
        memcpy((UWORK8 *)&strTcp.usSourcePort, (UWORK8 *)&gucaSegTemp[20], 20);  //读取TCP头数据
	}

	len = StrIp.usTotalLen;
	len -= 20;		 //长度是IC的总数据长度减去IP头的长度。其实就是IP数据包的长度.
	//计算TCP的校验和。是从IP的数据加上源IP和目标IP的值.而IP头的后8位就是源IP和目标IP,所以从12位开始
	sum = cksum((UWORK8 *)&gstaRevEthernet.ucaPacket[12], (8 + len));
	sum += 0x0006;     			 //计算的校验和加上TCP协议的值
	sum += len;					 //计算的校验和加上TCP包的长度
	result = (UWORK16)(sum + (sum >> 16));		   // In case there was a carry, add it back around
		
	if (result != 0xFFFF)			//如果校验和不对就返回
	{
		return;
    }
   SourcePort = strTcp.usDesPort;			//在接收的TCP数据包中,目标端口就是本机端口 
   DesPort = strTcp.usSourcePort;		    //在接收的TCP数据包中,源端口就是发送方的端口 
   memcpy((UWORK8 *)&IPSourceddress_buf[0],(UWORK8 *)&IPLocalAddress_buf[0],IP_LEN);                //回复TCP时,源IP就是本地IP    
   memcpy((UWORK8 *)&IPDestAddress_buf[0],(UWORK8 *)&StrIp.ucSourceIP[0],IP_LEN);          //回复TCP时,目标IP就是接收时的IP中的源IP 
   // See if the TCP segment is from someone we are already	connected to. 
   memcpy((UWORK8 *)&RcvIPAdrr,(UWORK8 *)&StrIp.ucSourceIP[0],IP_LEN);          //回复TCP时,目标IP就是接收时的IP中的源IP,也就是对方的IP

	for (i=0; i < 5; i++)		   //判断是哪一组IP地址的数据
	{
		if((RcvIPAdrr == StrConnection_buf[i].ipaddr) && (DesPort == StrConnection_buf[i].usDesPort))	   //要端口号与IP都相同才有效
		{   
			nr = i;
			break;
		}       
	}
	if(i == 5)			//与保存的5个IP地址都不同
	{
		for(p = 0; p < 5; p++)
		{
			if(StrConnection_buf[p].ipaddr == 0)
			{
				nr = p;
				break;
			}
		}
		if(p == 5)		   //发果5个IP地址都被占用。那就没有
		{
			return;
		}
	}
	memcpy((UWORK8 *)&StrConnection_buf[nr].ipaddr,(UWORK8 *)&StrIp.ucSourceIP[0],IP_LEN);          //回复TCP时,目标IP就是接收时的IP中的源IP,也就是对方的IP
	StrConnection_buf[nr].usDesPort = strTcp.usSourcePort;
	StrConnection_buf[nr].ucTRUECODE = strTcp.ucSERIESNUM;	   //确认号等于序列号
	StrConnection_buf[nr].ucSERIESNUM = strTcp.ucTRUECODE;   //序列号等确认号
//	StrConnection_buf[nr].timer = StrIp.ucTTL;   //读取收存时间
	StrConnection_buf[nr].timer = 0;
	StrConnection_buf[nr].inactivity = INACTIVITY_TIME;   //直接判断下一次的连接
   // Eventually put in protection against wrapping sequence numbers, for now make the client start over if his	 sequence number is close to wrapping
   if (strTcp.ucSERIESNUM > 0xFFFFFF00L) 		 //如果TCP的序号大于这个值,为无效值
   {
		StrConnection_buf[nr].ucTRUECODE = 0;	   //确认号等于序列号
		StrConnection_buf[nr].ucSERIESNUM = 0;   //序列号等确认号
		tcp_ReBack(FLG_RST, 20, nr);
		StrConnection_buf[nr].state = STATE_SYN_SEND;		//在发送连接请求后等待匹配的连接请求
		return;		
   }
   TcpFlag = strTcp.ucMOVENUM & 0x003f;
   if((TcpFlag & FLG_SYN) == FLG_SYN)		   //如果是一个同步位,表示新的连接
   {
		StrConnection_buf[nr].state = STATE_LISTEN;		// 监听来自远方TCP端口的连接请求
	}
	else if((TcpFlag & FLG_RST) == FLG_RST)		   //如果接收到一个重置位
	{
		StrConnection_buf[nr].state = STATE_LISTEN;		// 监听来自远方TCP端口的连接请求
	}
   header_len =  (strTcp.ucMOVENUM & 0xF000) >> 10;	 //记算TCP头的长度   data_len = len - header_len;						 //len在上面已算过是总个TCP的长度
   switch(StrConnection_buf[nr].state)
   {
   		case STATE_CLOSED:   			  // 监听来自远方TCP端口的连接请求
		case STATE_LISTEN:   			  // 监听来自远方TCP端口的连接请求
			LinkFlag = UDP;
			switch(TcpFlag)
			{
				case FLG_SYN:		   //如果是一个同步位,表示新的连接
					StrConnection_buf[nr].ucTRUECODE += 1;	   //序列号加1
					StrConnection_buf[nr].ucSERIESNUM = initial_sequence_nr;	  //我的序列号
//					initial_sequence_nr += 64000L;
					initial_sequence_nr += 200L;
					tcp_ReBack(FLG_SYN | FLG_ACK, 24, nr);
					StrConnection_buf[nr].state = STATE_SYN_RECEIVED;			//在收到和发送一个连接请求后等待对连接请求的确认
					break;
				case FLG_ACK | FLG_FIN: 		   //收到结束位(本机先发中止位时,收到确认后就关闭了.)
					StrConnection_buf[nr].ucTRUECODE += 1;	   //确认号等于序列号
					tcp_ReBack(FLG_ACK, 20, nr);		 //回复结束的确认位
					StrConnection_buf[nr].state = STATE_CLOSED;			//在收到和发送一个连接请求后等待对连接请求的确认
					StrConnection_buf[nr].ipaddr = 0;					//IP地址为0
					LinkFlag = UDP;
					break;
				default:
					StrConnection_buf[nr].ucTRUECODE = 0;	   //确认号等于序列号
					StrConnection_buf[nr].ucSERIESNUM = 0;   //序列号等确认号
					tcp_ReBack(FLG_RST, 20, nr);
					StrConnection_buf[nr].ipaddr = 0;		//在发送连接请求后等待匹配的连接请求
					StrConnection_buf[nr].state = STATE_LISTEN;		//在发送连接请求后等待匹配的连接请求
					break;
			}
			break;
		case STATE_SYN_RECEIVED:	   //在收到和发送一个连接请求后等待对连接请求的确认
			StrConnection_buf[nr].ucBakSERIESNUM = StrConnection_buf[nr].ucSERIESNUM;	   //建立连接后,保存系列号
			StrConnection_buf[nr].ucBakTRUECODE = StrConnection_buf[nr].ucTRUECODE;
			StrConnection_buf[nr].state = STATE_ESTABLISHED;		//代表一个打开的连接,数据可以传送给用户
			LinkFlag = TCP;
			break;

		case STATE_SYN_SEND:	 		  //在发送连接请求后等待匹配的连接请求
			switch(TcpFlag)
			{
				case FLG_RST | FLG_ACK:
					StrConnection_buf[nr].ucTRUECODE += 1;	   //确认号等于序列号
					StrConnection_buf[nr].ucSERIESNUM = strTcp.ucTRUECODE;   //序列号等确认号
					tcp_ReBack(FLG_ACK, 20, nr);					//回复确认后,

⌨️ 快捷键说明

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