TCP协议实验Word下载.docx
《TCP协议实验Word下载.docx》由会员分享,可在线阅读,更多相关《TCP协议实验Word下载.docx(14页珍藏版)》请在冰豆网上搜索。
最后将报文交由输入有限状态机处理,有限状态机对报文进行处理,转换状态。
根据当前的状态并调用stud_tcp_output函数完成tcp建连、数据传递时返回ACK、tcp断连等工作
●TCP分组发送函数stud_tcp_output()
判断需要发送的报文类型,根据报的类型对包中的相应字段进行设置,判断是否可以发送〔发送窗口不为0〕。
构造TCP数据报文并发送。
填写TCP报文各字段的内容和数据,转换字节序,计算校验和,然后调用发送流程的下层接口函数sendIpPkt()发送。
●stud_tcp_socket()函数
分配相应的socketfd并且新建TCB表项,并对成员变量进行初始化
●stud_tcp_connect()函数
设定目的IPv4地址和端口,源IPv4地址和端口;
初始化TCB结构中的相关变量;
设定TCB中的输入状态为SYN-SENT,及其它相关变量,准备发送SYN报文;
调用发送流程的下层接口函数stud_tcp_output()发送SYN报文〔发送类型为PACKET_TYPE_SYN〕;
等待“三次握手〞完成后返回,建立连接成功;
或者出错返回。
●stud_tcp_send()函数
判断是否处于ESTABLISHED状态;
将应用层协议的数据拷贝到TCB的输入缓冲区;
调用stud_tcp_output()发送TCP的数据报文〔发送类型为PACKET_TYPE_DATA〕;
同时等待ACK以实现停等式协议
●stud_tcp_recv()函数
从TCB的输入缓冲区读出数据;
将数据交给应用层协议。
●stud_tcp_close()函数
在正常情况下〔ESTABLISHED状态〕,进行相应状态转换,非正常情况下〔SYN-SENT状态〕,直接删除TCB结构后退出;
调用发送流程下层接口函数stud_tcp_output()发送FIN报文〔发送类型为PACKET_TYPE_FIN〕;
等待回应的ACK报文,收到后成功返回,或者出错返回;
删除相应的TCB表项。
实验总结
通过本次实验,加深了对TCP协议的原理和设计实现的机制的了解,对TCP协议有了更具体的认识,对概论课的学习有很大的帮助!
附:
上机代码〔注释〕
#include"
sysInclude.h"
externvoidtcp_DiscardPkt(char*pBuffer,inttype);
externvoidtcp_sendReport(inttype);
externvoidtcp_sendIpPkt(unsignedchar*pData,UINT16len,unsignedintsrcAddr,unsignedintdstAddr,UINT8ttl);
externintwaitIpPacket(char*pBuffer,inttimeout);
externunsignedintgetIpv4Address();
externunsignedintgetServerIpv4Address();
#defineBUFFER_SIZE1024
#defineTIMEOUT5
enumstatus{CLOSED,SYN_SENT,ESTABLISHED,FIN_WAIT_1,FIN_WAIT_2,TIME_WAIT};
//状态
intgSrcPort=2007;
intgDstPort=2006;
intgSeqNum=1;
intgAckNum=0;
structTCB{
intsocketfd;
UINT32srcAddr;
UINT32dstAddr;
UINT16srcPort;
UINT16dstPort;
UINT32seq;
UINT32ack;
UINT16windowSize;
UINT8state;
TCB*nextTcb;
TCB(){//用于TCP报文接收发送流程
socketfd=0;
srcAddr=getIpv4Address();
dstAddr=getServerIpv4Address();
srcPort=gSrcPort;
dstPort=gDstPort;
seq=gSeqNum;
ack=gAckNum;
windowSize=1;
state=CLOSED;
nextTcb=NULL;
}
TCB(intfd){//用于客户端socket函数的构建函数
socketfd=fd;
};
UINT16CalcChecksum(char*pBuffer,intlen,UINT32srcAddr,UINT32dstAddr)
{
inttcp_len=len+12;
UINT32checkSum=0;
if(tcp_len&
0x1==1)
tcp_len+=1;
char*buffer=newchar[tcp_len];
memset(buffer,0,tcp_len);
memcpy(buffer+12,pBuffer,len);
*((UINT32*)buffer)=htonl(srcAddr);
*((UINT32*)(buffer+4))=htonl(dstAddr);
buffer[9]=6;
//传输层协议号
*((UINT16*)(buffer+10))=htons(len);
for(inti=0;
i<
tcp_len;
i+=2){
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)&
dstAddr==dstAddr)&
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)
if(ack!
=tcb->
seq+1)
tcp_DiscardPkt(pBuffer,STUD_TCP_TEST_SEQNO_ERROR);
/*有限状态机转换*/
if((tcb->
state==SYN_SENT)&
(flags==0x12))
tcb->
seq=ack;
ack=seq+1;
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->
srcPort,tcb->
dstPort,tcb->
srcAddr,tcb->
dstAddr);
state=ESTABLISHED;
}
elseif((tcb->
state==FIN_WAIT_1)&
(flags==0x10))
state=FIN_WAIT_2;
state==FIN_WAIT_2)&
(flags==0x11))
state=TIME_WAIT;
state=CLOSED;
return0;
voidstud_tcp_output(char*pData,unsignedshortlen,unsignedcharflag,unsignedshortsrcPort,unsignedshortd