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

📄 tcp.c

📁 基于51单片机和RTL8019以太网控制器的嵌入式以太网控制程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
					// Use system clock for initial sequence number
					EA = 0;
					conxn[index].my_sequence = initial_sequence_nr;
					initial_sequence_nr += 64000L;
					EA = 1;

					// Send header options with the next message
					// Since timestamps are optional and we do not use
					// them, do not have to send them
					// After sending the SYN ACK the client browser will
					// blast me with 2 messages, an ACK, and a HTTP GET
					tcp_send(&TCPSend,FLG_SYN | FLG_ACK, 28, index);

					// My SYN flag increments my sequence number
					// My sequence number is always updated to point to
					// the next byte to be sent.  So the incoming ack
					// number should equal my sequence number
					conxn[index].my_sequence++;

					conxn[index].state = STATE_SYN_RCVD;
//					if (debug) PrintStr("TCP: Entered SYN RCVD state\r");
				}
				else
				{
					// Sender is out of sync so send reset
					InerClose(index);
					tcp_send(&TCPSend,FLG_RST, 20, NO_CONNECTION);
				}
				break;

			case STATE_SYN_RCVD:
				// He may already be sending me data - should process it
				conxn[index].his_sequence += data_len;
				conxn[index].his_ack = packACK;

				if (pRxdnet->tcpframe.control & FLG_FIN)
				{
					// His FIN counts as a byte of data
					conxn[index].his_sequence++;
					tcp_send(&TCPSend,FLG_ACK, 20, index);
					conxn[index].state = STATE_CLOSE_WAIT;
//					if (debug) PrintStr("TCP: Entered CLOSE_WAIT state\r");

        			// At this point we would normally wait for the	application
					// to close.  For now, send FIN right away.
					tcp_send(&TCPSend,FLG_FIN | FLG_ACK, 20, index);
					conxn[index].my_sequence++;   // For my FIN
					conxn[index].state = STATE_LAST_ACK;
//					if (debug) PrintStr("TCP: Entered LAST ACK state\r");
				}

				// Make sure he is ACKing my SYN
				else if (packACK == conxn[index].my_sequence)
				{
					conxn[index].state = STATE_ESTABLISHED;
//					if (debug) PrintStr("TCP: Entered ESTABLISHED state\r");
					// If sender sent data ignore it and he will resend
					// Do not send response because we received no

					//--------------------------------------------------------
					//
					//					进入连接状态,可以发送数据
					//
					//--------------------------------------------------------
					//调用服务器OnConnect()回调函数,该函数在TCPListen时被实体化
					(* conxn[index].connect)();
				}
				break;
			case STATE_ESTABLISHED:
				conxn[index].his_ack = packACK;

				if (pRxdnet->tcpframe.control & FLG_FIN)
				{
					// His FIN counts as a byte of data
					conxn[index].his_sequence++;
					tcp_send(&TCPSend,FLG_ACK, 20, index);
					conxn[index].state = STATE_CLOSE_WAIT;
//					if (debug) PrintStr("TCP: Entered CLOSE_WAIT state\r");

        			// At this point we would normally wait for the	application
					// to close.  For now, send FIN immediately.
					tcp_send(&TCPSend,FLG_FIN | FLG_ACK, 20, index);
					conxn[index].my_sequence++;   // For my FIN
					conxn[index].state = STATE_LAST_ACK;
//					if (debug) PrintStr("TCP: Entered LAST ACK state\r");
				}
				else if (data_len != 0)
				{
					//先判断对方的序列号是否小于conxn[index].his_sequence
					if(packSeq < conxn[index].his_sequence)
					{
						//说明对方丢失一个ACK
						//发生重传
						conxn[index].his_sequence = packSeq + data_len;
						
						tcp_send(&TCPSend,FLG_ACK,20, index); 		// Send ACK
						//重定保活定时器
						conxn[index].aty_timer = INACTIVITY_TIME;
						conxn[index].aty_stat = ATY_ACTIVE;
					//	seq = conxn[index].my_sequence + conxn[index].iLen;
					//	PrintLong(seq);
					//	PrintStr("-");
					//	PrintLong(pRxdnet->tcpframe.acknumber);
					//	PrintStr(" ");
					//	PrintByte(conxn[index].iLen);
					//	PrintStr(" ");
						/*
						//己方丢失对方ACK
						if(conxn[index].iLen != 0 && pRxdnet->tcpframe.acknumber == seq)
						{	
							if(conxn[index].pUnAcked->bUsed)
							{
								//已经ACKED了在 pUnAcked里的包
								conxn[index].pUnAcked->bUsed=FALSE;	
								//增加自己的sequence
								conxn[index].my_sequence=seq;
								conxn[index].iLen=0;
								//如果有包等待发送
								if(conxn[index].pWaitForSend->bUsed)
								{
										//检查空间是否够
									if(conxn[index].pWaitForSend->iLen<=conxn[index].pUnAcked->iLen)
									{	
										conxn[index].pWaitForSend->bUsed=FALSE;
										//发送数据,并将包登记进未ACKED里面
										tcp_senddata(&TCPSend,conxn[index].pWaitForSend->pBuf,conxn[index].pWaitForSend->iLen+20,index,0);
									}
								}
							}
							else
							{
								//ACK缓冲区未被用,则检查WaitForSend区域
								if(conxn[index].pWaitForSend->bUsed)
								{
									//检查空间是否够
									if(conxn[index].pWaitForSend->iLen<=conxn[index].pUnAcked->iLen)
									{
										conxn[index].pWaitForSend->bUsed=FALSE;
										//发送数据,并将包登记进未ACKED里面
										tcp_senddata(&TCPSend,conxn[index].pWaitForSend->pBuf,conxn[index].pWaitForSend->iLen+20,index,0);
									}
								}
							}
						}*/
					}
					else
					{
						conxn[index].his_sequence += data_len;
						seq = conxn[index].my_sequence + conxn[index].iLen;
		//				PrintLong(seq);
		//				PrintStr("-");
	//					PrintLong(pRxdnet->tcpframe.acknumber);
	//					PrintStr(" ");
	//					PrintByte(conxn[index].iLen);
	//					PrintStr(" ");
						if(packACK == seq)
						{
							//重定保活定时器
							conxn[index].aty_timer = INACTIVITY_TIME;
							conxn[index].aty_stat = ATY_ACTIVE;
							//增加自己的sequence
							conxn[index].my_sequence=seq;
							conxn[index].iLen=0;
							tcp_send(&TCPSend,FLG_ACK,20, index); 		// Send ACK
							if(conxn[index].pUnAcked->bUsed)
							{
								//已经ACKED了在 pUnAcked里的包
								conxn[index].pUnAcked->bUsed=FALSE;	
								//如果有包等待发送
								if(conxn[index].pWaitForSend->bUsed)
								{
									//检查空间是否够
									if(conxn[index].pWaitForSend->iLen<=conxn[index].pUnAcked->iLen)
									{
										conxn[index].pWaitForSend->bUsed=FALSE;
										//发送数据,并将包登记进未ACKED里面
										tcp_senddata(&TCPSend,conxn[index].pWaitForSend->pBuf,conxn[index].pWaitForSend->iLen+20,index,0);
									}
								}
							}
							else
							{
								//ACK缓冲区未被用,则检查WaitForSend区域
								if(conxn[index].pWaitForSend->bUsed)
								{
									//检查空间是否够
									if(conxn[index].pWaitForSend->iLen <= conxn[index].pUnAcked->iLen)
									{
										conxn[index].pWaitForSend->bUsed=FALSE;
										//发送数据,并将包登记进未ACKED里面
										tcp_senddata(&TCPSend,conxn[index].pWaitForSend->pBuf,conxn[index].pWaitForSend->iLen+20,index,0);
									}
								}
							}
							//	调用回调函数,通知应用程序收到数据。
							(* conxn[index].recv)(pRxdnet->tcpframe.tcpdata,data_len);
						}
					}
				}
				else
				{
					seq = conxn[index].my_sequence+conxn[index].iLen;
					if(packACK == seq)
					{
						//重定保活定时器
						conxn[index].aty_timer = INACTIVITY_TIME;
						conxn[index].aty_stat = ATY_ACTIVE;
						if(conxn[index].pUnAcked->bUsed)
						{
							//已经ACKED了在 pUnAcked里的包
							conxn[index].pUnAcked->bUsed=FALSE;
							//增加自己的sequence
							conxn[index].my_sequence=seq;
							conxn[index].iLen=0;		//iLen已经用于增加了my_sequence
							//如果有包等待发送
							if(conxn[index].pWaitForSend->bUsed)
							{
								//检查空间是否够
								if(conxn[index].pWaitForSend->iLen<=conxn[index].pUnAcked->iLen)
								{
									conxn[index].pWaitForSend->bUsed = FALSE;
									//发送数据,并将包登记进未ACKED里面
									tcp_senddata(&TCPSend,conxn[index].pWaitForSend->pBuf,conxn[index].pWaitForSend->iLen+20,index,0);
								}
							}
						}
					}
					else
					{
						//假如对方发送保活定时器请求,则返回一个正确ack
						seq = seq - 1;
						if(seq == packACK)
						{
							tcp_send(&TCPSend,FLG_ACK,20, index);	
						}
					}
				}		
				break;

			case STATE_CLOSE_WAIT:
				// With this code, should not get here
				//因为在进入STATE_CLOSE_WAIT后这边马上发送一个FIN,直接进入LAST_ACK状态
//				if (debug) PrintStr("TCP: Oops! Rcvd unexpected message\r");

				break;

			case STATE_LAST_ACK:
				conxn[index].his_ack = packACK;

				// If he ACK's my FIN then close
				if (packACK == conxn[index].my_sequence)
				{
					conxn[index].state = STATE_CLOSED;
					InerClose(index);
					just_closed = TRUE;
				}
				break;
			case STATE_FIN_WAIT_1:
				// He may still be sending me data - should process it
				conxn[index].his_sequence += data_len;
				conxn[index].his_ack = packACK;

				if (pRxdnet->tcpframe.control & FLG_FIN)
				{
					// His FIN counts as a byte of data
					conxn[index].his_sequence++;
					tcp_send(&TCPSend,FLG_ACK, 20, index);

					// If he has ACK'd my FIN then we can close connection
					if (packACK == conxn[index].my_sequence)
					{
         				conxn[index].state = STATE_TIME_WAIT;
//         				if (debug) PrintStr("TCP: Entered TIME_WAIT state\r");

         				conxn[index].state = STATE_CLOSED;
						InerClose(index);  // Free up connection
         				just_closed = TRUE;
      				}
					else
					{
						// He has not ACK'd my FIN.  This happens when there is a simultaneous
						// close - I got his FIN but he has not yet ACK'd my FIN
						conxn[index].state = STATE_CLOSING;
//						if (debug) PrintStr("TCP: Entered CLOSING state\r");
					}
				}
				else if (packACK == conxn[index].my_sequence)
				{
					// He has ACK'd my FIN but has not sent a FIN yet himself
					conxn[index].state = STATE_FIN_WAIT_2;
				//	if (debug) PrintStr("TCP: Entered FIN_WAIT_2 state\r");
				}
				break;
			case STATE_FIN_WAIT_2:
      				// He may still be sending me data - should process it
				conxn[index].his_sequence += data_len;
      				conxn[index].his_ack = packACK;

      				if (pRxdnet->tcpframe.control & FLG_FIN)
      				{
         				conxn[index].his_sequence++; // For his FIN flag
         				tcp_send(&TCPSend,FLG_ACK, 20, index);
         				conxn[index].state = STATE_TIME_WAIT;
//         				if (debug) PrintStr("TCP: Entered TIME_WAIT state\r");
         			//	conxn[index].state = STATE_CLOSED;
						InerClose(index); // Free up struct area
         				just_closed = TRUE;
      				}
      				break;
			case STATE_TIME_WAIT:
      				// With this code, should not get here
					//因为在进入FIN_WAIT_2后这边的连接直接进入CLOSED
//      				if (debug) PrintStr("TCP: Oops! In TIME_WAIT state\r");
      				break;
			case STATE_CLOSING:
      				// Simultaneous close has happened. I have received his FIN
      				// but he has not yet ACK'd my FIN.  Waiting for ACK.
				// Will not receive data in this state
				conxn[index].his_ack = packACK;

				if (packACK == conxn[index].my_sequence)
      				{
		   				conxn[index].state = STATE_TIME_WAIT;
 //        				if (debug) PrintStr("TCP: Entered TIME_WAIT state\r");

         				// Do not send any response to his ACK
         		//		conxn[index].state = STATE_CLOSED;
						InerClose(index);  // Free up struct area
         				just_closed = TRUE;
      				}
      				break;
			case STATE_SYN_SENT:
				//这些代码用于当连接为客户端是的状况
				//// If incoming segment contains SYN and  ACK, then handle
				if ((pRxdnet->tcpframe.control & FLG_SYN) && (pRxdnet->tcpframe.control & FLG_ACK))
				{
					conxn[index].my_sequence++;		//for my SYN
					conxn[index].ip.words[0]= pRxdnet->ipframe.sourceip[0];
					conxn[index].ip.words[1]= pRxdnet->ipframe.sourceip[1];
					conxn[index].port = pRxdnet->tcpframe.sourceport;
					conxn[index].localport=LOCAL_PORT;
					conxn[index].state = STATE_ESTABLISHED;
					conxn[index].socket_type = CLIENT;
					conxn[index].his_sequence = 1 + packSeq;
					conxn[index].his_ack = packACK;
					tcp_send(&TCPSend,FLG_ACK, 20, index); 		// Send ACK
					//调用OnConnect()函数
					(* conxn[index].connect)();
				}
				break;
			default:
//      				if (debug) PrintStr("TCP: Error, no handler\r");
      				break;
		}
		// This is for debug, to see when conxn closes
   		if (just_closed)
   		{
      			just_closed = FALSE;
      			if (debug) PrintStr("TCP: Closed connection ");
   		}

	}
}



//------------------------------------------------------------------------
// This runs every 0.5 seconds.  If the other end has not ACK'd
// everyting we have sent, it re-sends it.  To save RAM space, we
// regenerate a segment rather than keeping a bunch of segments
// hanging around eating up RAM.  A connection should not be in an
// opening or closing state when this timer expires, so we simply
// send a reset.
//
//	If a connection is in the ESTABLISHED state when the timer expires
// then we have just sent a web page so re-send the page
//2006-02-13:修改重传的次数及时间
//------------------------------------------------------------------------
void tcp_retransmit()
{
   unsigned char nr;
   // Scan through all active connections
   for (nr = 0; nr < NO_CONNECTION; nr++)
   {
      if ((conxn[nr].ip.dwords != 0) && (conxn[nr].timer))
      {
         // Decrement the timer and see if it hit 0
         conxn[nr].timer--;
         if (conxn[nr].timer == 0)
         {
			 
            // Socket just timed out. If we are not in ESTABLISHED state
            // something is amiss so send reset and close connection
            if (conxn[nr].state != STATE_ESTABLISHED)
            {
				// Send reset and close connection
				if (debug) PrintStr("TCP: Timeout, sending reset\r");
				tcp_send(&TCPSend,FLG_RST, 20, nr);
				InerClose(nr);
				return;
            }
            else
            {
               // Socket is in ESTABLISHED state. First make sure his
               // ack number is not bogus.
               if (conxn[nr].his_ack > conxn[nr].my_sequence)
               {
					// Send reset and close connection
					if (debug) PrintStr("TCP: Timeout, sending reset2\r");
					tcp_send(&TCPSend,FLG_RST, 20, nr);
					InerClose(nr);
					return;
               }
               // We always increment our sequence number immediately
			   // after sending, so the ack number from the other end
			   // should be equal to our sequence number.  If it is less,
			   // it means he lost some of our data.
        //       if (conxn[nr].his_ack < conxn[nr].my_sequence)
		//	   {
			   else
			   {
				   if(conxn[nr].pUnAcked->bUsed)
				   {
						conxn[nr].retries++;
						if (conxn[nr].retries <= RESENDCOUNT)
						{
                   			// The only thing we send is a web page, and it looks
                  			// like other end did not get it, so resend
                  			// but do not increase my sequence number
                  			if (debug) PrintStr("TCP: Timeout, resending data\r");
							tcp_senddata(&TCPSend,conxn[nr].pUnAcked->pBuf,conxn[nr].pUnAcked->iLen+20,nr,1);
							//重置保活定时器
							conxn[nr].aty_timer = INACTIVITY_TIME;
						}
						else
						{
							conxn[nr].retries = 0;
							if (debug) PrintStr("TCP: Giving up, sending reset\r");
							// Send reset and close connection
               				tcp_send(&TCPSend,FLG_RST, 20, nr);
							InerClose(nr);
               			}
				   }
               }
			}
         }
      }
	}
}




//------------------------------------------------------------------------
// 该函数每隔2个小时执行,向对方发送一个ARP请求,如果搜到arp echo,则接着发送
//一个ack,该ack序号为正常ack-1

⌨️ 快捷键说明

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