修正Tcp::Connect中Callback的逻辑处理。

Tcp服务端测试通过,Tcp客户端丢失了 三次握手的第三个包
This commit is contained in:
Stone 2014-12-05 09:23:55 +00:00
parent a0735da8cb
commit c847b6117f
7 changed files with 76 additions and 46 deletions

View File

@ -71,7 +71,7 @@ bool OnTcpReceived(TcpSocket* socket, TCP_HEADER* tcp, byte* buf, uint len)
bool HttpReceived(TcpSocket* socket, TCP_HEADER* tcp, byte* buf, uint len)
{
debug_printf("Tcp::Received From ");
debug_printf("Http::Received From ");
TinyIP::ShowIP(socket->RemoteIP);
debug_printf(":%d with Payload=%d ", socket->RemotePort, len);
Sys.ShowString(buf, len);

View File

@ -109,7 +109,7 @@ bool ArpSocket::Process(MemoryStream* ms)
return true;
}
bool RequestCallback(TinyIP* tip, void* param)
bool RequestCallback(TinyIP* tip, void* param, MemoryStream& ms)
{
ETH_HEADER* eth = (ETH_HEADER*)tip->Buffer;
ARP_HEADER* arp = (ARP_HEADER*)eth->Next();

View File

@ -51,7 +51,7 @@ bool IcmpSocket::Process(MemoryStream* ms)
return true;
}
bool PingCallback(TinyIP* tip, void* param)
bool PingCallback(TinyIP* tip, void* param, MemoryStream& ms)
{
ETH_HEADER* eth = (ETH_HEADER*)tip->Buffer;
IP_HEADER* _ip = (IP_HEADER*)eth->Next();

View File

@ -3,7 +3,7 @@
#define NET_DEBUG DEBUG
bool Callback(TinyIP* tip, void* param);
bool Callback(TinyIP* tip, void* param, MemoryStream& ms);
TcpSocket::TcpSocket(TinyIP* tip) : Socket(tip)
{
@ -20,9 +20,18 @@ TcpSocket::TcpSocket(TinyIP* tip) : Socket(tip)
if(g_tcp_port < 1024) g_tcp_port = 1024;
BindPort = g_tcp_port++;
seqnum = 0xa;
// 我们仅仅递增第二个字节这将允许我们以256或者512字节来发包
static uint seqnum = 0xa;
Seq = seqnum << 8;
seqnum += 2;
Ack = 0;
Status = Closed;
OnAccepted = NULL;
OnReceived = NULL;
OnDisconnected = NULL;
}
string TcpSocket::ToString()
@ -93,6 +102,10 @@ void TcpSocket::OnProcess(TCP_HEADER* tcp, MemoryStream& ms)
debug_printf("\r\n");
#endif
// 下次主动发数据时用该序列号因为对方Ack确认期望下次得到这个序列号
Seq = __REV(tcp->Ack);
Ack = __REV(tcp->Seq) + len + 1;
// 第一次同步应答
if (tcp->Flags & TCP_FLAGS_SYN) // SYN连接请求标志位为1表示发起连接的请求数据包
{
@ -132,7 +145,7 @@ void TcpSocket::OnAccept(TCP_HEADER* tcp, uint len)
}
//第二次同步应答
Head(tcp, 1, false);
SetSeqAck(tcp, 1, false);
SetMss(tcp);
// 需要用到MSS所以采用4个字节的可选段
@ -156,7 +169,7 @@ void TcpSocket::Accepted2(TCP_HEADER* tcp, uint len)
}
//第二次同步应答
Head(tcp, 1, true);
SetSeqAck(tcp, 1, true);
Send(tcp, 0, TCP_FLAGS_ACK);
}
@ -168,7 +181,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER* tcp, uint len)
{
if (tcp->Flags & (TCP_FLAGS_FIN | TCP_FLAGS_RST)) //FIN结束连接请求标志位。为1表示是结束连接的请求数据包
{
Head(tcp, 1, true);
SetSeqAck(tcp, 1, true);
Send(tcp, 0, TCP_FLAGS_ACK);
}
else
@ -189,7 +202,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER* tcp, uint len)
if(!rs)
{
// 发送ACK通知已收到
Head(tcp, 1, true);
SetSeqAck(tcp, 1, true);
Send(tcp, 0, TCP_FLAGS_ACK);
return;
}
@ -205,7 +218,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER* tcp, uint len)
#endif
}
// 发送ACK通知已收到
Head(tcp, len, true);
SetSeqAck(tcp, len, true);
//Send(buf, 0, TCP_FLAGS_ACK);
//TcpSend(buf, len);
@ -221,10 +234,19 @@ void TcpSocket::OnDisconnect(TCP_HEADER* tcp, uint len)
// RST是对方紧急关闭这里啥都不干
if(tcp->Flags & TCP_FLAGS_FIN)
{
Head(tcp, 1, true);
SetSeqAck(tcp, 1, true);
//Close(tcp, 0);
Send(tcp, 0, TCP_FLAGS_ACK | TCP_FLAGS_PUSH | TCP_FLAGS_FIN);
}
else
{
#if NET_DEBUG
debug_printf("Tcp OnDisconnect "); // 打印发送方的ip
TinyIP::ShowIP(RemoteIP);
debug_printf(":%d Flags=0x%02x", RemotePort, tcp->Flags);
debug_printf("\r\n");
#endif
}
}
void TcpSocket::Send(TCP_HEADER* tcp, uint len, byte flags)
@ -247,7 +269,7 @@ void TcpSocket::Send(TCP_HEADER* tcp, uint len, byte flags)
Tip->SendIP(IP_TCP, (byte*)tcp, tcp->Size() + len);
}
void TcpSocket::Head(TCP_HEADER* tcp, uint ackNum, bool opSeq)
void TcpSocket::SetSeqAck(TCP_HEADER* tcp, uint ackNum, bool opSeq)
{
/*
A发送位码为SYN1Seq=x的数据包到服务器B由SYN=1A要求建立联机
@ -260,22 +282,16 @@ void TcpSocket::Head(TCP_HEADER* tcp, uint ackNum, bool opSeq)
Ack
*/
//TCP_HEADER* tcp = Header;
int ack = tcp->Ack;
uint ack = tcp->Ack;
tcp->Ack = __REV(__REV(tcp->Seq) + ackNum);
if (!opSeq)
{
// 我们仅仅递增第二个字节这将允许我们以256或者512字节来发包
tcp->Seq = __REV(seqnum << 8);
// step the inititial seq num by something we will not use
// during this tcp session:
seqnum += 2;
/*tcp->Seq = __REV(seqnum);
seqnum++;*/
//tcp->Seq = 0;
tcp->Seq = __REV(Seq);
}
else
{
tcp->Seq = ack;
//tcp->Seq = __REV(Seq);
}
}
@ -300,7 +316,7 @@ TCP_HEADER* TcpSocket::Create()
return (TCP_HEADER*)(Tip->Buffer + sizeof(ETH_HEADER) + sizeof(IP_HEADER));
}
void TcpSocket::Ack(uint len)
void TcpSocket::SendAck(uint len)
{
TCP_HEADER* tcp = Create();
tcp->Init(true);
@ -339,7 +355,9 @@ void TcpSocket::Send(const byte* buf, uint len)
// 发送的时候采用LocalPort
LocalPort = BindPort;
Head(tcp, len, true);
//SetSeqAck(tcp, len, true);
tcp->Seq = __REV(Seq);
tcp->Ack = __REV(Ack);
Send(tcp, len, TCP_FLAGS_PUSH);
Tip->LoopWait(Callback, this, 5000);
@ -362,9 +380,8 @@ bool TcpSocket::Connect(IPAddress ip, ushort port)
TCP_HEADER* tcp = Create();
tcp->Init(true);
tcp->Seq = 0;
//seqnum = 0;
Head(tcp, 0, false);
tcp->Seq = 0; // 仅仅是为了Ack=0tcp->Seq还是会被Socket的顺序Seq替代
SetSeqAck(tcp, 0, false);
SetMss(tcp);
Status = SynSent;
@ -388,32 +405,40 @@ bool TcpSocket::Connect(IPAddress ip, ushort port)
return false;
}
bool Callback(TinyIP* tip, void* param)
bool Callback(TinyIP* tip, void* param, MemoryStream& ms)
{
ETH_HEADER* eth = (ETH_HEADER*)tip->Buffer;
ETH_HEADER* eth = ms.Retrieve<ETH_HEADER>();
if(eth->Type != ETH_IP) return false;
IP_HEADER* _ip = (IP_HEADER*)eth->Next();
IP_HEADER* _ip = ms.Retrieve<IP_HEADER>();
if(_ip->Protocol != IP_TCP) return false;
TcpSocket* socket = (TcpSocket*)param;
// 这里不移动数据流方便后面调用Process
TCP_HEADER* tcp = (TCP_HEADER*)_ip->Next();
// 检查端口
if(tcp->DestPort != socket->Port) return false;
ushort port = __REV16(tcp->DestPort);
if(port != socket->Port) return false;
socket->Header = tcp;
//if(Status == SynSent)
{
// 处理。如果对方回发第二次握手包,或者终止握手
MemoryStream ms(tip->Buffer, tip->BufferSize);
socket->Process(&ms);
}
//else
if(socket->Status == TcpSocket::SynSent)
{
if(tcp->Flags & TCP_FLAGS_ACK)
{
socket->Status = TcpSocket::SynAck;
// 处理。如果对方回发第二次握手包,或者终止握手
//MemoryStream ms(tip->Buffer, tip->BufferSize);
socket->Process(&ms);
return true;
}
}
return true;
return false;
}
bool TcpSocket::OnWrite(const byte* buf, uint len)

View File

@ -7,7 +7,9 @@
class TcpSocket : public Socket, public ITransport
{
private:
byte seqnum;
//byte seqnum;
uint Seq; // 序列号,本地发出数据包
uint Ack; // 确认号,对方发送数据包的序列号+1
TCP_HEADER* Create();
@ -17,7 +19,8 @@ public:
{
Closed = 0,
SynSent = 1,
Established = 2,
SynAck = 2,
Established = 3,
}TCP_STATUS;
ushort Port; // 本地端口接收该端口数据包。0表示接收所有端口的数据包
@ -48,9 +51,9 @@ public:
virtual string ToString();
protected:
void Ack(uint len);
void SendAck(uint len);
void Head(TCP_HEADER* tcp, uint ackNum, bool cp_seq);
void SetSeqAck(TCP_HEADER* tcp, uint ackNum, bool cp_seq);
void SetMss(TCP_HEADER* tcp);
void Send(TCP_HEADER* tcp, uint len, byte flags);
@ -68,11 +71,11 @@ protected:
};
// Tcp客户端
class TcpClient : public TcpSocket
/*class TcpClient : public TcpSocket
{
public:
TcpClient(TinyIP* tip);
};
};*/
#endif

View File

@ -205,7 +205,9 @@ bool TinyIP::LoopWait(LoopFilter filter, void* param, uint msTimeout)
}
// 业务
if(filter(this, param)) return true;
ms.SetPosition(0);
ms.Length = len;
if(filter(this, param, ms)) return true;
// 用不到数据包交由系统处理
ms.SetPosition(0);

View File

@ -34,7 +34,7 @@ public:
};
class TinyIP;
typedef bool (*LoopFilter)(TinyIP* tip, void* param);
typedef bool (*LoopFilter)(TinyIP* tip, void* param, MemoryStream& ms);
// 精简以太网协议。封装以太网帧以及IP协议不包含其它协议实现仅提供底层支持。
class TinyIP