📄 tcp.c
字号:
#include "cpu_reg.h"
#include "string.h"
#include "ip.h"
#include "tcp.h"
Uint16 MyMAC[] = {0xE002,0xA04C,0x7A7E}; //02-E0-4C-A0-7E-7A
Uint16 MyIP[] = {0xA8C0,0x0B01}; //192.168.1.11
Uint16 RemoteIP[] = {0xA8C0,0x2801}; //192.168.1.40
Uint16 SubnetMask[] = {0xFFFF,0x00FF}; //255.255.255.000
Uint16 GatewayIP[] = {0xA8C0,0x0101}; //192.168.1.1
//variable
Uint16 RemoteMAC[3]; //48 bit MAC
Uint16 RecdFrameMAC[3];
Uint16 RecdFrameIP[2];
Uint16 TCPRemotePort;
Uint32 TCPSegNr; //本次要发送的TCP序号
Uint32 TCPAckNr; //本次收到的TCP确认
Uint32 TCPSendNextNr; //下次发送的TCP序号
Uint32 TCPSent_UnAck; //我的还未得到确认的TCP序号
Uint32 TCPIRSeq; //我收到的对方的TCP序号
Uint16 TCPTimeout;
Uint16 TCPConnected;
Uint16 TCPRxDataLenth;
Uint16 TCPTxDataLenth;
//Uint16 TCPResendSeqNr; //需要重新发送的TCP序号
Uint16 TCPResendCount;
Uint16 TCPResendNumFlag;
Uint16 RxTCPDataSuccess;
Uint16 TxSuccessFlag;
Uint16 TxFrameSize;
Uint16 TCPStatus;
Uint16 DestMaxSegSize;
Uint16 RecdIpFrameLenth;
Uint16 TCPActiveOpenFlag;
Uint16 ARPAnswerSuccessFlag;
extern Uint16 TxEthnetFrameBuffer[1518/2];
extern Uint16 RxEthnetFrameBuffer[1518/2];
/***************TCP*******************/
void TCP_Init(void)
{
TCPTimeout = 0;
TCPStatus = 0; //TCP_STATE_LISTEN状态
TxSuccessFlag = 0;
TCPConnected = 0;
TCPResendNumFlag = 0;
TCPSendNextNr = 0x0000;
TCPActiveOpenFlag = 0;
TCPResendCount = 20;
ARPAnswerSuccessFlag = 0;
}
void Delete_Socket(void)
{
TCPConnected = 0; //没有建立连接
TCPStatus = 0; //TCP_STATE_LISTEN状态
TCPResendNumFlag = 0;
//----------
TCPSegNr = TCPSegNr + 10; //本次要发送的TCP序号
//TCPResendSeqNr = TCPSegNr;
//----------
}
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
void TCPActiveOpen(void) //主动打开
{
Uint16 CalcCkSum;
TCPActiveOpenFlag=1; //主动打开标志置1
if((TCPStatus == TCP_STATE_CLOSED) || (TCPStatus == TCP_STATE_LISTEN))
{
TCPAckNr = 0; //要发送的TCP确认号
TCPSegNr = TCPSendNextNr; //本次发送的TCP序号,TCP_Init()中TCPSendNextNr=0
//TCPResendSeqNr = TCPSegNr; //存储用来重新发送的本次发送的TCP序号
TCPSent_UnAck = TCPSegNr; //本次发送之后我还未收到确认的序号
//SYN报文段不能携带数据,但要消耗掉一个序号,所以TCPSendNexNr要加1
TCPSendNextNr = TCPSegNr + 1; //下次要发送的TCP序号
DestMaxSegSize = 560;
//Ethnet MAC帧首部
memcpy((TxEthnetFrameBuffer + ETH_HEADER_START), &RemoteMAC, 3); //目的MAC地址
memcpy((TxEthnetFrameBuffer + ETH_HEADER_START + 3), &MyMAC, 3); //本机MAC地址
*(TxEthnetFrameBuffer + ETH_HEADER_START + 6) = SwapWord(Frame_IP); //协议
//IP首部
/******************************************
* 00------04--------08----------------16 *
* | 版本 | 首部长度| 区分服务 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 0) = SwapWord(Ip_Edition); //首部长度的单位是32位字,固定部分是20字节即5位字
/******************************************
* 00----------------------------------16 *
* | 总长度 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 1) = SwapWord((IP_HEADER_SIZE + TCP_HEADER_SIZE + 4) * 2); //总长度:首部和数据之和的长度
/******************************************
* 00----------------------------------16 *
* | 标识 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 2) = 0;
/******************************************
* 00----03----------------------------16 *
* | 标志| 片偏移 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 3) = 0;
/******************************************
* 00----------------08----------------16 *
* | 生存时间 | 协议 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 4) = SwapWord((DEFUALT_TTL << 8) | PROTOCOL_TCP);
/******************************************
* 00----------------------------------16 *
* | 首部检验和 | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + IP_HEADER_START + 5) = 0;
memcpy((TxEthnetFrameBuffer + IP_HEADER_START + 6), &MyIP, 2); //源IP地址
memcpy((TxEthnetFrameBuffer + IP_HEADER_START + 8), &RemoteIP, 2); //目的IP地址
CalcCkSum = CalcCheckSum((TxEthnetFrameBuffer + IP_HEADER_START), IP_HEADER_SIZE, 0, 0);
if(!CalcCkSum)
CalcCkSum=0xFFFF;
*(TxEthnetFrameBuffer + IP_HEADER_START + 5) = CalcCkSum; //检验和
//TCP首部
*(TxEthnetFrameBuffer + TCP_HEADER_START + 0) = SwapWord(MY_TCP_PORT); //源端口
*(TxEthnetFrameBuffer + TCP_HEADER_START + 1) = SwapWord(TCPRemotePort); //目的端口
WriteDWord((TxEthnetFrameBuffer + TCP_HEADER_START + 2),TCPSegNr); //32位序号,本报文段所发送的数据的第一个字节的序号,同步位SYN=1
WriteDWord((TxEthnetFrameBuffer + TCP_HEADER_START + 4),TCPAckNr); //32位确认号,其若确认号=N,则表明到序号N-1为止的所有数据都已正确收到
/******************************************
* 00------04------------10------------16 *
* |数据偏移| 保留 | | *
* ------------------------------------ *
******************************************/
*(TxEthnetFrameBuffer + TCP_HEADER_START + 6) = SwapWord(0x7000 | TCP_CODE_SYN); //数据偏移指出TCP报文段的数据起始处距离TCP报文段的起始处有多远,实际就是TCP首部长度
*(TxEthnetFrameBuffer + TCP_HEADER_START + 7) = SwapWord(1024); //窗口,指的是发送本报文段的一方的接收窗口,指出了现在允许对方发送的数据量
*(TxEthnetFrameBuffer + TCP_HEADER_START + 8) = 0; //检验和
*(TxEthnetFrameBuffer + TCP_HEADER_START + 9) = 0; //紧急指针,指出紧急数据的末尾在报文段中的位置
//TCP选项:最大报文段长度
*(TxEthnetFrameBuffer + TCP_HEADER_START + 10) = SwapWord(0x0204); //kind = 2,一字节;len = 4,一字节
*(TxEthnetFrameBuffer + TCP_HEADER_START + 11) = SwapWord(MY_MAX_SEG_SIZE); //TCP报文中的数据字段的最大长度,2字节
/********************************************
* Kind Length Meaning *
* ---- ------ ------- *
* 0 - End of option list. *
* 1 - No-Operation. *
* 2 4 Maximum Segment Size. *
********************************************/
//This option code may be used between options, for example, to align the beginning of a subsequent option on a word boundary.
*(TxEthnetFrameBuffer + TCP_HEADER_START + 12) = SwapWord(0x0101);
*(TxEthnetFrameBuffer + TCP_HEADER_START + 13) = SwapWord(0x0101);
CalcCkSum = CalcCheckSum((TxEthnetFrameBuffer + TCP_HEADER_START), 14, 1, 0);
if(!CalcCkSum)
CalcCkSum = 0xFFFF;
*(TxEthnetFrameBuffer + TCP_HEADER_START + 8) = CalcCkSum;
TxFrameSize = ETH_HEADER_SIZE + IP_HEADER_SIZE + 14;
SendFrame(TxEthnetFrameBuffer, TxFrameSize);
TCPStatus = TCP_STATE_SYN_SENT; //进入TCP_STATE_SYN_SENT状态
}
}
void TCP_Send_Reset(void)
{
*(TxEthnetFrameBuffer + TCP_HEADER_START + 7) = 0; //窗口,现在允许对方发送的数据量为0
Prepare_TCP_Frame(0);
}
/*
void Resend_Packet(void)
{
Prepare_TCP_Frame(TCP_CODE_SYN);
TCPResendCount = 20;
}
*/
void Process_Resend_Buff(void)
{
if(TCPResendCount > 0)
TCPResendCount--; //防止TCP死锁
//if(TCPResendSeqNr < TCPSent_UnAck)
//TCPResendNumFlag = 0;
if(!TCPResendCount) //TCPResendCount = 0
{
TCPResendNumFlag++;
if(TCPResendNumFlag == TCP_MAX_RE_TXDNUM) //TCP_MAX_RE_TXDNUM = 8
Delete_Socket(); //重传8次不成功,删除socket
else
SendFrame(TxEthnetFrameBuffer,TxFrameSize); //每200ms重传一次
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -