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