📄 tcp.c
字号:
// 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 + -