TCP协议实验.docx
- 文档编号:15017968
- 上传时间:2023-06-29
- 格式:DOCX
- 页数:16
- 大小:24.02KB
TCP协议实验.docx
《TCP协议实验.docx》由会员分享,可在线阅读,更多相关《TCP协议实验.docx(16页珍藏版)》请在冰点文库上搜索。
TCP协议实验
网络课第四次上机实验报告
------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协议有了更具体的认识,对概论课的学习有很大的帮助!
附:
上机代码(注释)
#include""
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;
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;i 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->; 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*)(buffer+8)));
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TCP 协议 实验