1 / 11
文档名称:

TCP协议实验.pdf

格式:pdf   大小:381KB   页数:11页
下载后只包含 1 个 PDF 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

TCP协议实验.pdf

上传人:mama1 2023/3/13 文件大小:381 KB

下载得到文件列表

TCP协议实验.pdf

文档介绍

文档介绍:该【TCP协议实验 】是由【mama1】上传分享,文档一共【11】页,该文档可以免费在线阅读,需要了解更多关于【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;最后将报文交由输入有限状态机处理,有限状态机
对报文进行处理,
连、数据传递时返回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"sysInclude。h”
externvoidtcp_DiscardPkt(char*pBuffer,inttype);
externvoidtcp_sendReport(inttype);
externvoidtcp_sendIpPkt(unsignedchar*pData,UINT16len,unsignedint
srcAddr,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<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)&&(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,unsigned
intdstAddr)
{
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,int
flags)
{:.
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)));
stud_tcp_output(NULL,0,PACKET_TYPE_ACK,tcb->srcPort,
tcb->dstPort,tcb—〉srcAddr,tcb->dstAddr);
}
else
{
return-1;
}
}
else
{
return—1;
}
if(pre!=NULL)
pre—>nextTcb=tcb—>nextTcb;
else
tcbLinkTable=tcb->nextTcb;:.
deletetcb;
return0;
}