checkSum+=*((UINT16*)(buffer+i));
}
checkSum=(checkSum&0xFFFF)+(checkSum>>16);
checkSum=~checkSum;
returncheckSum;
}
TCB*tcbLinkTable=NULL;//TCB链表
/*通过两端的IP地址和端口号寻找TCB表项*/
TCB*findTCB(UINT32srcAddr,UINT16srcPort,UINT32dstAddr,UINT16dstPort)
{
TCB*tcb=tcbLinkTable;
while(tcb!
=NULL)
{
if((tcb->srcAddr==srcAddr)&&(tcb->srcPort==srcPort)&&(tcb->dstAddr==dstAddr)&&(tcb->dstPort==dstPort))
returntcb;
tcb=tcb->nextTcb;
}
returnNULL;
}
intstud_tcp_input(char*pBuffer,unsignedshortlen,unsignedintsrcAddr,unsignedintdstAddr)
{
/*检查校验和*/
if(CalcChecksum(pBuffer,len,ntohl(srcAddr),ntohl(dstAddr))!
=0)
return-1;
UINT16srcPort=ntohs(*(UINT16*)pBuffer);
UINT16dstPort=ntohs(*(UINT16*)(pBuffer+2));
UINT32seq=ntohl(*((UINT32*)(pBuffer+4)));
UINT32ack=ntohl(*((UINT32*)(pBuffer+8)));
UINT8flags=(pBuffer[13]&0x13);
TCB*tcb=findTCB(ntohl(dstAddr),dstPort,ntohl(srcAddr),srcPort);
if(tcb==NULL)
{
return-1;
}
if(ack!
=tcb->seq+1)
{
tcp_DiscardPkt(pBuffer,STUD_TCP_TEST_SEQNO_ERROR);
return-1;
}
/*有限状态机转换*/
if((tcb->state==SYN_SENT)&&(flags==0x12))
{
tcb->seq=ack;
tcb->ack=seq+1;
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
tcb->state=ESTABLISHED;
}
elseif((tcb->state==FIN_WAIT_1)&&(flags==0x10))
{
tcb->state=FIN_WAIT_2;
}
elseif((tcb->state==FIN_WAIT_2)&&(flags==0x11))
{
tcb->ack=seq+1;
tcb->seq=ack;
tcb->state=TIME_WAIT;
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
tcb->state=CLOSED;
}
return0;
}
voidstud_tcp_output(char*pData,unsignedshortlen,unsignedcharflag,unsignedshortsrcPort,unsignedshortdstPort,unsignedintsrcAddr,unsignedintdstAddr)
{
TCB*tcb=findTCB(srcAddr,srcPort,dstAddr,dstPort);//寻找TCB项
if(tcbLinkTable==NULL)//用于TCP报文接收发送流程
{
tcb=newTCB();
tcbLinkTable=tcb;
}
if(tcb==NULL||tcb->windowSize==0)
return;
/*构造新的发送报文*/
unsignedchar*packet=newunsignedchar[len+20];
memset(packet,0,len+20);
memcpy(packet+20,pData,len);
*(UINT16*)(packet)=htons(tcb->srcPort);
*(UINT16*)(packet+2)=htons(tcb->dstPort);
*(UINT32*)(packet+4)=htonl(tcb->seq);
*((UINT32*)(packet+8))=htonl(tcb->ack);
packet[12]=20<<2;
switch(flag)
{
casePACKET_TYPE_SYN:
packet[13]=0x02;
tcb->state=SYN_SENT;//发送SYN报文,状态转移为SYN_SENT
break;
casePACKET_TYPE_ACK:
packet[13]=0x10;
break;
casePACKET_TYPE_SYN_ACK:
packet[13]=0x12;
break;
casePACKET_TYPE_FIN:
packet[13]=0x01;
break;
casePACKET_TYPE_FIN_ACK:
packet[13]=0x11;
tcb->state=FIN_WAIT_1;
break;
casePACKET_TYPE_DATA:
break;
}
*((UINT16*)(packet+14))=htons(tcb->windowSize);
*((UINT16*)(packet+16))=CalcChecksum((char*)packet,len+20,srcAddr,dstAddr);
tcp_sendIpPkt(packet,len+20,tcb->srcAddr,tcb->dstAddr,255);
return;
}
intstud_tcp_socket(intdomain,inttype,intprotocol)
{
staticintsocketfd=1;
TCB*tcb=newTCB(socketfd++);
tcb->nextTcb=tcbLinkTable;
tcbLinkTable=tcb;
returntcb->socketfd;
}
intstud_tcp_connect(intsockfd,structsockaddr_in*addr,intaddrlen)
{
charbuffer[BUFFER_SIZE];
TCB*tcbPointer=tcbLinkTable;
while((tcbPointer!
=NULL)&&(tcbPointer->socketfd!
=sockfd))
tcbPointer=tcbPointer->nextTcb;
TCB*tcb=tcbPointer;//找到TCB相应表项
if(tcb==NULL)
return-1;
/*初始化源和目的的地址及端口号*/
tcb->srcAddr=getIpv4Address();
tcb->srcPort=gSrcPort;
tcb->dstAddr=ntohl(addr->sin_addr.s_addr);
tcb->dstPort=ntohs(addr->sin_port);
/*建立连接:
发送SYN报文*/
stud_tcp_output(NULL,0,PACKET_TYPE_SYN,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
/*接收SYN_ACK报文*/
if(waitIpPacket(buffer,TIMEOUT)==-1||(buffer[13]&0x13)!
=0x12)
return-1;
tcb->seq=ntohl(*((UINT32*)(buffer+8)));
tcb->ack=ntohl(*((UINT32*)(buffer+4)))+1;
/*发送ACK报文,建立连接完成*/
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
tcb->state=ESTABLISHED;
return0;
}
intstud_tcp_send(intsockfd,constunsignedchar*pData,unsignedshortdatalen,intflags)
{
charbuffer[BUFFER_SIZE];
TCB*tcbPointer=tcbLinkTable;
while((tcbPointer!
=NULL)&&(tcbPointer->socketfd!
=sockfd))
tcbPointer=tcbPointer->nextTcb;
TCB*tcb=tcbPointer;//找到TCB相应表项
if(tcb==NULL||tcb->state!
=ESTABLISHED)
return-1;
/*发送DATA报文*/
stud_tcp_output((char*)pData,datalen,PACKET_TYPE_DATA,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
/*等待接收ACK*/
if(waitIpPacket(buffer,TIMEOUT)==-1)
return-1;
if((buffer[13]&0x13)!
=0x10)
return-1;
tcb->seq=ntohl(*((UINT32*)(buffer+8)));
tcb->ack=ntohl(*((UINT32*)(buffer+4)))+1;
return0;
}
intstud_tcp_recv(intsockfd,unsignedchar*pData,unsignedshortdatalen,intflags)
{
charbuffer[BUFFER_SIZE];
intlen=0;
TCB*tcbPointer=tcbLinkTable;
while((tcbPointer!
=NULL)&&(tcbPointer->socketfd!
=sockfd))
tcbPointer=tcbPointer->nextTcb;
TCB*tcb=tcbPointer;
if(tcb==NULL||tcb->state!
=ESTABLISHED)
return-1;
/*等待接收数据*/
if((len=waitIpPacket(buffer,TIMEOUT))==-1)
return-1;
intheader_length=(buffer[12]>>2)&0x3C;
memcpy(pData,buffer+header_length,len-header_length);
tcb->seq=ntohl(*((UINT32*)(buffer+8)));
tcb->ack=ntohl(*((UINT32*)(buffer+4)))+(len-header_length);
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
return0;
}
intstud_tcp_close(intsockfd)
{
charbuffer[BUFFER_SIZE];
TCB*pre=NULL;
TCB*tcb=tcbLinkTable;
while((tcb!
=NULL)&&(tcb->socketfd!
=sockfd))
{
pre=tcb;
tcb=tcb->nextTcb;
}
if(tcb==NULL)
return-1;
if(tcb->state!
=ESTABLISHED)
{
if(pre!
=NULL)
{
pre->nextTcb=tcb->nextTcb;
}
else
{
tcbLinkTable=tcb->nextTcb;
}
deletetcb;
return-1;
}
stud_tcp_output(NULL,0,PACKET_TYPE_FIN_ACK,tcb->srcPort,tcb->dstPort,tcb->srcAddr,tcb->dstAddr);
if(waitIpPacket(buffer,TIMEOUT)==-1)
return-1;
if((buffer[13]&0x13)==0x10)
{
tcb->state=FIN_WAIT_2;
tcb->seq=ntohl(*((UINT32*)(buffer+8)));
tcb->ack=ntohl(*((UINT32*)(buffer+4)))+1;
if(waitIpPacket(buffer,TIMEOUT)==-1)
return-1;
if((buffer[13]&0x13)==0x11)
{
tcb->state=TIME_WAIT;
tcb->ack=ntohl(*((UINT32*)(buffer+4)))+1;
tcb->seq=ntohl(*((UINT32*)(buff