TCP数据包的发送和接收设计报告.docx

上传人:b****8 文档编号:10902122 上传时间:2023-02-23 格式:DOCX 页数:15 大小:164.30KB
下载 相关 举报
TCP数据包的发送和接收设计报告.docx_第1页
第1页 / 共15页
TCP数据包的发送和接收设计报告.docx_第2页
第2页 / 共15页
TCP数据包的发送和接收设计报告.docx_第3页
第3页 / 共15页
TCP数据包的发送和接收设计报告.docx_第4页
第4页 / 共15页
TCP数据包的发送和接收设计报告.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

TCP数据包的发送和接收设计报告.docx

《TCP数据包的发送和接收设计报告.docx》由会员分享,可在线阅读,更多相关《TCP数据包的发送和接收设计报告.docx(15页珍藏版)》请在冰豆网上搜索。

TCP数据包的发送和接收设计报告.docx

TCP数据包的发送和接收设计报告

湖北工业大学

课程设计报告

设计题目:

TCP数据包的发送和接收

专业:

计算机科学与技术

班级:

10计科2班

学号:

1010311211

姓名:

吕红杰

指导老师:

涂军

 

 

一.设计题目

发送和接收TCP数据包

二.设计要求

1.正确理解题意;

2.具有良好的编程规范和适当的注释;

3.有详细的文档,文档中应包括设计题目涉及的基础知识、设计思路、程序流程图、程序清单、开发中遇到的问题及解决方法、设计中待解决的问题及改进方向。

三.需求分析

TCP是一种面向连接的、可靠的传输层协议。

TCP协议工作在网络层IP协议的基础上。

本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个TCP数据包,发送给目的主机,并在目的主机接收此TCP数据包,将数据字段显示显示在标准输出上。

四.具体设计

1.创建一个原始套接字,并设置IP头选项

SOCKETsock;

sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);

或者:

sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);

这里,设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。

为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPED。

在本课程设计中,发送TCP包时隐藏了自己的IP地址,因此我们要自己填充IP头,设置IP头操作选项。

其中flag设置为ture,并设定IP_HDRINCL选项,表明自己来构造IP头。

setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&Flag,sizeof(Flag));

inttimeout=1000;

setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));

在这里我们使用基本套接字SOL_SOCKET,设置SO_SNDTIMEO表示使用发送超时设置,超时时间设置为1000ms。

2.构造IP头和TCP头

这里,IP头和TCP头以及TCP伪部的构造请参考下面它们的数据结构。

typedefstruct_iphdr//定义IP首部

{

UCHARh_lenver;//4位首部长度+4位IP版本号

UCHARtos;//8位服务类型TOS

USHORTtotal_len;//16位总长度(字节)

USHORTident;//16位标识

USHORTfrag_and_flags;//3位标志位

UCHARttl;//8位生存时间TTL

UCHARproto;//8位协议(TCP,UDP或其他)

USHORTchecksum;//16位IP首部校验和

ULONGsourceIP;//32位源IP地址

ULONGdestIP;//32位目的IP地址

}IP_HEADER;

typedefstructpsd_hdr//定义TCP伪首部

{

ULONGsaddr;//源地址

ULONGdaddr;//目的地址

UCHARmbz;//没用

UCHARptcl;//协议类型

USHORTtcpl;//TCP长度

}PSD_HEADER;

typedefstruct_tcphdr//定义TCP首部

{

USHORTth_sport;//16位源端口

USHORTth_dport;//16位目的端口

ULONGth_seq;//32位序列号

ULONGth_ack;//32位确认号

UCHARth_lenres;//4位首部长度/6位保留字

UCHARth_flag;//6位标志位

USHORTth_win;//16位窗口大小

USHORTth_sum;//16位校验和

USHORTth_urp;//16位紧急数据偏移量

}TCP_HEADER;

3.计算校验和的子函数

在填充数据包的过程中,需要调用计算校验和的函数checksum两次,分别用于校验IP头和TCP头部(加上伪头部),其实现代码如下:

USHORTchecksum(USHORT*buffer,intsize)

{

unsignedlongcksum=0;

while(size>1)

{

cksum+=*buffer++;

size-=sizeof(USHORT);

}

if(size)

{

cksum+=*(UCHAR*)buffer;

}

cksum=(cksum>>16)+(cksum&0xffff);

cksum+=(cksum>>16);

return(USHORT)(~cksum);

}

4.流程图

五.实验内容

1.先用vc++编译运行程序代码

2.用命令指示符运行Debug下的sendTCP

3.输入源ip和端口及目的ip和端口

4.输入发送内容

5.发送完成

六.附代码

#include

#include

#include

#include

#include

#include

#include

#include

#pragmacomment(lib,"ws2_32.lib")

#defineIPVER4//IP协议预定

#defineMAX_BUFF_LEN65500//发送缓冲区最大值

typedefstructip_hdr//定义IP首部

{

UCHARh_verlen;//4位首部长度,4位IP版本号

UCHARtos;//8位服务类型TOS

USHORTtotal_len;//16位总长度(字节)

USHORTident;//16位标识

USHORTfrag_and_flags;//3位标志位

UCHARttl;//8位生存时间TTL

UCHARproto;//8位协议(TCP,UDP或其他)

USHORTchecksum;//16位IP首部校验和

ULONGsourceIP;//32位源IP地址

ULONGdestIP;//32位目的IP地址

}IP_HEADER;

typedefstructtsd_hdr//定义TCP伪首部

{

ULONGsaddr;//源地址

ULONGdaddr;//目的地址

UCHARmbz;//没用

UCHARptcl;//协议类型

USHORTtcpl;//TCP长度

}PSD_HEADER;

typedefstructtcp_hdr//定义TCP首部

{

USHORTth_sport;//16位源端口

USHORTth_dport;//16位目的端口

ULONGth_seq;//32位序列号

ULONGth_ack;//32位确认号

UCHARth_lenres;//4位首部长度/6位保留字

UCHARth_flag;//6位标志位

USHORTth_win;//16位窗口大小

USHORTth_sum;//16位校验和

USHORTth_urp;//16位紧急数据偏移量

}TCP_HEADER;

//CheckSum:

计算校验和的子函数

USHORTchecksum(USHORT*buffer,intsize)

{

unsignedlongcksum=0;

while(size>1)

{

cksum+=*buffer++;

size-=sizeof(USHORT);

}

if(size)

{

cksum+=*(UCHAR*)buffer;

}

cksum=(cksum>>16)+(cksum&0xffff);

cksum+=(cksum>>16);

return(USHORT)(~cksum);

}

intReadData(char*str,intmaxlen)

{

intreadlen=0;

charch=NULL;

if(str==NULL||maxlen<=0)

{

printf("ReadDataError!

!

!

\n");

return0;//failed

}

printf("InputData(EndByCtrl+Z):

\n");

while(maxlen)

{

ch=getchar();

if(ch==EOF)break;

str[readlen++]=ch;

maxlen--;

}

str[readlen]=NULL;

returnreadlen;

}

intmain(intargc,char*argv[])

{

WSADATAWSAData;

SOCKETsock;

IP_HEADERipHeader;

TCP_HEADERtcpHeader;

PSD_HEADERpsdHeader;

charSendto_Buff[MAX_BUFF_LEN];//发送缓冲区

unsignedshortcheck_Buff[MAX_BUFF_LEN];//检验和缓冲区

chartcp_send_data[1000];

intread_data_len=0;

BOOLflag;

intrect,nTimeOver;

if(argc!

=5)

{

printf("Usage:

SendTcpsoruce_ipsource_portdest_ipdest_port\n");

returnfalse;

}

read_data_len=ReadData(tcp_send_data,1000);

if(read_data_len<=0)return1;

if(WSAStartup(MAKEWORD(2,2),&WSAData)!

=0)

{

printf("WSAStartupError!

\n");

returnfalse;

}

if((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,

WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)

{

printf("SocketSetupError!

\n");

returnfalse;

}

flag=true;

if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,

(char*)&flag,sizeof(flag))==SOCKET_ERROR)

{

printf("setsockoptIP_HDRINCLerror!

\n");

returnfalse;

}

nTimeOver=1000;

if(setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,

(char*)&nTimeOver,sizeof(nTimeOver))==SOCKET_ERROR)

{

printf("setsockoptSO_SNDTIMEOerror!

\n");

returnfalse;

}

//填充IP首部

ipHeader.h_verlen=(IPVER<<4|sizeof(ipHeader)/sizeof(unsignedlong));

ipHeader.tos=(UCHAR)0;

ipHeader.total_len=htons((unsignedshort)sizeof(ipHeader)+sizeof(tcpHeader)+read_data_len);

ipHeader.ident=0;//16位标识

ipHeader.frag_and_flags=0;//3位标志位

ipHeader.ttl=128;//8位生存时间

ipHeader.proto=IPPROTO_TCP;//协议类型

ipHeader.checksum=0;//检验和暂时为0

ipHeader.sourceIP=inet_addr(argv[1]);//32位源IP地址

ipHeader.destIP=inet_addr(argv[3]);//32位目的IP地址

//计算IP头部检验和

memset(check_Buff,0,MAX_BUFF_LEN);

memcpy(check_Buff,&ipHeader,sizeof(IP_HEADER));

ipHeader.checksum=checksum(check_Buff,sizeof(IP_HEADER));

//构造TCP伪首部

psdHeader.saddr=ipHeader.sourceIP;

psdHeader.daddr=ipHeader.destIP;

psdHeader.mbz=0;

psdHeader.ptcl=ipHeader.proto;

psdHeader.tcpl=htons(sizeof(TCP_HEADER)+read_data_len);

//填充TCP首部

tcpHeader.th_dport=htons(atoi(argv[4]));//16位目的端口号

tcpHeader.th_sport=htons(atoi(argv[2]));//16位源端口号

tcpHeader.th_seq=0;//SYN序列号

tcpHeader.th_ack=0;//ACK序列号置为0

//TCP长度和保留位

tcpHeader.th_lenres=(sizeof(tcpHeader)/sizeof(unsignedlong)<<4|0);

tcpHeader.th_flag=2;//修改这里来实现不同的标志位探测,2是SYN,1是//FIN,16是ACK探测等等

tcpHeader.th_win=htons((unsignedshort)16384);//窗口大小

tcpHeader.th_urp=0;//偏移大小

tcpHeader.th_sum=0;//检验和暂时填为0

//计算TCP校验和

memset(check_Buff,0,MAX_BUFF_LEN);

memcpy(check_Buff,&psdHeader,sizeof(psdHeader));

memcpy(check_Buff+sizeof(psdHeader),&tcpHeader,sizeof(tcpHeader));

memcpy(check_Buff+sizeof(PSD_HEADER)+sizeof(TCP_HEADER),

tcp_send_data,read_data_len);

tcpHeader.th_sum=checksum(check_Buff,sizeof(PSD_HEADER)+

sizeof(TCP_HEADER)+read_data_len);

//填充发送缓冲区

memset(Sendto_Buff,0,MAX_BUFF_LEN);

memcpy(Sendto_Buff,&ipHeader,sizeof(IP_HEADER));

memcpy(Sendto_Buff+sizeof(IP_HEADER),

&tcpHeader,sizeof(TCP_HEADER));

memcpy(Sendto_Buff+sizeof(IP_HEADER)+sizeof(TCP_HEADER),

tcp_send_data,read_data_len);

intdatasize=sizeof(IP_HEADER)+sizeof(TCP_HEADER)+read_data_len;

//发送数据报的目的地址

SOCKADDR_INdest;

memset(&dest,0,sizeof(dest));

dest.sin_family=AF_INET;

dest.sin_addr.s_addr=inet_addr(argv[3]);

dest.sin_port=htons(atoi(argv[4]));

rect=sendto(sock,Sendto_Buff,datasize,0,

(structsockaddr*)&dest,sizeof(dest));

if(rect==SOCKET_ERROR)

{

printf("senderror!

:

%d\n",WSAGetLastError());

returnfalse;

}

else

printf("\nsendok!

\n");

closesocket(sock);

WSACleanup();

return1;

}

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

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1