发送TCP数据包.docx

上传人:b****7 文档编号:9820803 上传时间:2023-02-06 格式:DOCX 页数:13 大小:236.88KB
下载 相关 举报
发送TCP数据包.docx_第1页
第1页 / 共13页
发送TCP数据包.docx_第2页
第2页 / 共13页
发送TCP数据包.docx_第3页
第3页 / 共13页
发送TCP数据包.docx_第4页
第4页 / 共13页
发送TCP数据包.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

发送TCP数据包.docx

《发送TCP数据包.docx》由会员分享,可在线阅读,更多相关《发送TCP数据包.docx(13页珍藏版)》请在冰豆网上搜索。

发送TCP数据包.docx

发送TCP数据包

发送TCP数据包

1.3相关知识

编制本程序前要对TCP协议有一定的了解。

当应用程序有报文需要通过TCP发送时,它就将此应用层报文传送给执行TCP协议的传输实体。

TCP传输实体将用户数据加上TCP报头,形成TCP数据包,在TCP数据包上增加IP头部,形成IP包。

下图显示的是TCP数据包和IP包的关系。

 

TCP协议的传输单元为报文段,其格式如图所示。

报文段报头的长度为20B~60B。

其中固定长度为20B,报文段长度最多为40B。

TCP报文段主要包括以下字段。

•埠号:

埠号字段包括源埠号和目的埠号。

每个埠号的长度是16位,分别表示发送该

TCP包的应用进程的埠号和接收该TCP包的应用进程的埠号。

有。

•序号:

长度为32位。

由于TCP协议是面向数据流的,它所传送的报文段可以视为连续的数据流,因此需要给每一个字节编号。

序号字段的“序号”指的是本报文段数据的第一个字节的顺序旦

节的序号。

•报头长度:

该字段长度为4位。

TCP报头长度是以4B为一个单元来计算的,实际上报头长度在20B^60B子间。

因此这个字段的值在5~15之间。

•保留:

长度为6位,留作今后使用,目前全部置0。

•控制:

这个字段定义了6种不同的标志,每个标志占一位,在同一时间可以设置一位或多位。

URG为1时,表明有需要紧急处理的数据。

ACK为1时,表明确认号的字段有效。

PST位为1时,表明要强制切断连接。

SYN位为1时,表明有确立连接的请求,这时,把序号字段的初始值作为序号字段的值,以便开始通信。

FIN为1时,表明发送方已经没有

资料发送了。

•窗口大小:

长度为16位,窗口对应的数据是以字节为单位的数据,因此最多能够传送的数据为65535R

•紧急指针:

该字段的长度为16位,指向必须紧急处理的数据的位置,只有当标志URG=1时紧急指针才有效。

从TCP报头后面的报文资料开始,到紧急指针所指出的长度的数据,就是必须紧急处理的数据。

•选项:

该字段可以多达40B,包括单字节选项和多字节选项。

TCP报头以及应用

•校验和:

该字段长度多达16位,校验和的校验范围包括伪头部、层来的数据。

其计算方法与IP协议头部的校验的计算方法一样。

伪头部为12B,它本身并不是TCP数据包的真正头部,只是在计算校验和时,临时和TCP数据包连接在一起。

伪头部的格式如下图所示。

源IP地址

目的IP地址

1.4工作环境

软件:

MicrosoftVisualC++6.0;硬件:

PC机一台。

课程设计分析

本课程设计的目标是发送一个TCP资料包,可以利用原始套接字来完成这个工作。

整个程序由初始化原始套接字和发送TCP数据包两个部分组成。

2.1使用原始套接字

SOCKETsock;

sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);

或者:

sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPP

ED);

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

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

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

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

注意,如果设置IP_HDRINCL选项,那么必须具有administrator权限,要不就必须修改注册表:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameter\

修改键:

DisableRawSecurity(类型为DWORD),把值修改为1。

如果没有,就添加。

BOOLFlag=TRUE;

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.2定义IP头部、TCP头部和伪头部的数据结构

//定义IP首部

typedefstruct_iphdr

 

}IP_HEADER;

//定义TCP伪首部typedefstructpsd_hdr

}PSD_HEADER;

//定义TCP首部

typedefstruct_tcphdr

 

}TCP_HEADER;

2.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);

}

2.4程序流程图

 

源代码

#include

#include

#include

#include

#include

#include

#include

#include

#pragmacomment(lib,"ws2_32.lib")

 

#defineIPVER4

//IP协议预定

//源地址//目的地址//没用//协议类型//TCP长度

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

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

//8位服务类型TOS

//16位总长度(字节)

//16位标识

//3位标志位

//8位生存时间TTL

//8位协议(TCP,UDP或其它)

//16位IP首部校验和

//32位源IP地址

//32位目的IP地址

typedefstructtsd_hdr//定义TCP伪首部{ULONGsaddr;ULONGdaddr;

UCHARmbz;

UCHARptcl;USHORTtcpl;}PSD_HEADER;

typedefstructtcp_hdr//定义TCP首部{

//16位源埠

//16位目的端口

//32位序列号

//32位确认号

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

//6位标志位

//16位窗口大小

//16位校验和

//16位紧急数据偏移量

USHORTth_sport;

USHORTth_dport;

ULONGth_seq;

ULONGth_ack;

UCHARth_lenres;

UCHARth_flag;

USHORTth_win;

USHORTth_sum;

USHORTth_urp;

}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);

}

intmain(intargc,char*argv[]){

WSADATAWSAData;

SOCKETsock;

IP_HEADERipHeader;

TCP_HEADERtcpHeader;

PSD_HEADERpsdHeader;

charSendto_Buff[MAX_BUFF_LEN];//发送缓冲区unsignedshortcheck_Buff[MAX_BUFF_LEN];//检验和缓冲区constchartcp_send_data[]={"Thisismyhomeworkofnetwort,Iamhappy!

"};

BOOLflag;intrect,nTimeOver;if(argc!

=5)

printf("Useage:

SendTcpsoruce_ipsource_portdest_ipdest_port\n");returnfalse;

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)+sizeof(tcp_send_data));

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

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

ipHeader.ttl=128;//8位生存时间ipHeader.proto=IPPROTO_UDP;//协议类型ipHeader.checksum=0;/检/验和暂时为0ipHeader.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)+sizeof(tcp_send_data));

//填充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,sizeof(tcp_send_data));

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

//填充发送缓冲区

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,sizeof(tcp_send_data));

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

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

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("sendok!

\n");closesocket(sock);WSACleanup();return1;

}

谢谢大家下载,本文档下载后可根据实际情况进行编辑修改.再次谢谢大家下载.翱翔在知

识的海洋吧.

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

当前位置:首页 > 工程科技 > 能源化工

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

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