您好,欢迎访问三七文档
网络课第四次上机实验报告------TCP协议实验实验内容实验内容主要包括:设计保存TCP连接相关信息的数据结构(TCB);TCP协议的接收处理和封装发送;TCP协议提供的Socket函数接口。实验过程设计保存TCP连接相关信息的数据结构(TCB)用数据结构TCB为每一个TCP连接维护socketfd,srcAddr,dstAddr,srcPort,dstPort,seq,ack,windowSize,state这些状态信息。以链表形式组织多个连接,nextTcb指向下一个连接的数据结构。TCP分组接收函数stud_tcp_input()首先,检查校验和;然后通过字节序转换获取相应的信息,检查序列号。如果序列号不正确,则调用tcp_DiscardPkt;最后将报文交由输入有限状态机处理,有限状态机对报文进行处理,转换状态。根据当前的状态并调用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()函数判断是否处于ESTABLISHED状态;从TCB的输入缓冲区读出数据;将数据交给应用层协议。stud_tcp_close()函数在正常情况下(ESTABLISHED状态),进行相应状态转换,非正常情况下(SYN-SENT状态),直接删除TCB结构后退出;调用发送流程下层接口函数stud_tcp_output()发送FIN报文(发送类型为PACKET_TYPE_FIN);等待回应的ACK报文,收到后成功返回,或者出错返回;删除相应的TCB表项。实验总结通过本次实验,加深了对TCP协议的原理和设计实现的机制的了解,对TCP协议有了更具体的认识,对概论课的学习有很大的帮助!附:上机代码(注释)#includesysInclude.hexternvoidtcp_DiscardPkt(char*pBuffer,inttype);externvoidtcp_sendReport(inttype);externvoidtcp_sendIpPkt(unsignedchar*pData,UINT16len,unsignedintsrcAddr,unsignedintdstAddr,UINT8ttl);externintwaitIpPacket(char*pBuffer,inttimeout);externunsignedintgetIpv4Address();externunsignedintgetServerIpv4Address();#defineBUFFER_SIZE1024#defineTIMEOUT5enumstatus{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;seq=gSeqNum;ack=gAckNum;windowSize=1;state=CLOSED;nextTcb=NULL;}};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;itcp_len;i+=2){checkSum+=*((UINT16*)(buffer+i));}checkSum=(checkSum&0xFFFF)+(checkSum16);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]=202;switch(flag){casePACKET_TYPE_SYN:packet[13]=0x02;tcb-state=SYN_SENT;//发送SYN报文,状态转移为SYN_SENTbreak;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,le
本文标题:TCP协议实验
链接地址:https://www.777doc.com/doc-5362526 .html