TCP协议实验.docx

上传人:b****4 文档编号:4949538 上传时间:2023-05-07 格式:DOCX 页数:17 大小:25.76KB
下载 相关 举报
TCP协议实验.docx_第1页
第1页 / 共17页
TCP协议实验.docx_第2页
第2页 / 共17页
TCP协议实验.docx_第3页
第3页 / 共17页
TCP协议实验.docx_第4页
第4页 / 共17页
TCP协议实验.docx_第5页
第5页 / 共17页
TCP协议实验.docx_第6页
第6页 / 共17页
TCP协议实验.docx_第7页
第7页 / 共17页
TCP协议实验.docx_第8页
第8页 / 共17页
TCP协议实验.docx_第9页
第9页 / 共17页
TCP协议实验.docx_第10页
第10页 / 共17页
TCP协议实验.docx_第11页
第11页 / 共17页
TCP协议实验.docx_第12页
第12页 / 共17页
TCP协议实验.docx_第13页
第13页 / 共17页
TCP协议实验.docx_第14页
第14页 / 共17页
TCP协议实验.docx_第15页
第15页 / 共17页
TCP协议实验.docx_第16页
第16页 / 共17页
TCP协议实验.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

TCP协议实验.docx

《TCP协议实验.docx》由会员分享,可在线阅读,更多相关《TCP协议实验.docx(17页珍藏版)》请在冰点文库上搜索。

TCP协议实验.docx

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”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;

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,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

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2