计算机网络课程设计数据包发送和接受程序的实现.docx
- 文档编号:3833596
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:17
- 大小:65.23KB
计算机网络课程设计数据包发送和接受程序的实现.docx
《计算机网络课程设计数据包发送和接受程序的实现.docx》由会员分享,可在线阅读,更多相关《计算机网络课程设计数据包发送和接受程序的实现.docx(17页珍藏版)》请在冰点文库上搜索。
计算机网络课程设计数据包发送和接受程序的实现
发送和接受程序的实现
数据包发送和接受程序的实现
《计算机网络》课程设计
计算机学院
软件工程
10级⑷班
3110006379
陈泳蒸
2012年12月21日
数据包发送和接受程序的实现
一、设计题目与要求
1.设计题目
发送TCP数据包
2.设计要求
本设计的功能孚填充一个TCP数据包,并发送给目的主机。
1)以命令行形式运行:
SendTCPsourcejpsource_portdestjpdest_port,其中SendTCP是程序名,source_ip为源端IP地址,source_port为源端口号,destjp为目的地址,dest_port为目的端口号。
2)其他的TCP头部参数请自行设定。
3)数据字段为aThlsismyhomeworkofnetworkJamhappy!
4)成功发送后在屏幕上输出"sendOK”。
三、详细设计
本课程设计的目标是发送一个TCP数据包,可以利用原始套接字来完成这个工作。
整个程序由初始化原始套接字和发送TCP数据包两个部分组成。
当应用进程需要通过TCP发送时,它就将此应用层报文传送给执行TCP协议的传输实体。
TCP传输实体将用户数据加上TCP报头,形成TCP数
据包,在TCP数据包上增加IP头部,形成IP包。
如图-1显示的是TCP数据包和IP包得关系。
TCP协议的数据传输单位称为报文段,其格式如图-2所示。
报文段报头的长度是20B~60B,选项部分长度最多为40BoTCP报文段主要包括以下字段。
端口号:
端口号字段包括源端口号和目的端口号。
每个端口号的长度是16位,分别表示发送该TCP包的应用进程的端口号和接收该TCP包的应用进程的端口号。
1
pan4Q
nnr'n来fr
卩1
TH-HI
th来卜曲
图-1TCP数据包加上IP报头形成IP包
序号:
长度为32位。
由于TCP协议是面向数据流的,它所传送的报文段可以视为连续的数据流,因此需要给每一字节编号。
序号字段的“序号”指的是本报文段数据的第一个字节的序号。
确认号:
该字段的长度为32位,它表示接收端希望接收下一个TCP包的第一个字节的序号。
报文长度:
该字段长度为4位。
TCP报文长度是以4B为一个单元来计算的,实际上报文长度在20B~60B之间。
因此这个字段的值在5~15之间。
血dn旦
口砧旦
报文保URACPSRSSYFI
窗口大
0刍坦
保留:
长度为6位,留
做今后使用,目前全部
图・2TCP数据包头部的格式
置0.
控制:
这个字段定义了6种不同的标志,每一个标志占一位,在同一时间可以设置一位或多位。
URG位为1时,表明应尽快把数据传送给应用程序,否则表明允许数据在缓存中存放一段时间。
RST位为1时,表明要强制切断连接。
SYN位为1时,表明有确立连接的请求,这时,把序号字段的初始值作为序号字段的值,以便开始通信。
FIN位为1时,表明发送放已经没有数据发送了。
窗口大小:
长度为16位,指向必须紧急处理的数据的位置,因此最多能够传送的数据为
65535Bo
紧急指针:
该字段长度为16,指向必需紧急处理的位置,只有当标志URG=1时紧急指针才生效。
从TCP报头后面的报文数据开始,到紧急指针所指出长度的数据,就是必须紧急处理的数据。
选项:
该字段可以多达40B,包括单字节选项和多字节选项。
校验和:
该字段长度为16位,校验和的校验范围包括伪头部,TCP报头以及应用层来的数据。
其计算方法与IP协议头部校验和的计算方法一样。
伪头部为12B,它本身并不是TCP数据包的真头部,只是在计算校验和时,临时和TCP数据包连接在一起。
伪头部的格式如图-3所示
081624
31
源ip地址
00000000
协议号(6)
TCP长度
目的ip地址
1•创建一个原始套接字,并设置IP头选项
SOCKETsock;
sock
socket(AF_INET,SOCK_RAWJPPROTO_IP);
或者:
sock=WSASoccket(AF_INET,SOCK_RAW,IPP
ROTO_IP,NULL,0,WSA_FLAG_OVERLAPPE
D);
这里,设置了SOCK.RAW标志,表示我们声明的是一个原始套接字类型。
为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPEDo在本课程设计
中,发送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*)&timeout9sizeof(timeout));
在这里我们使用基本套接字SOL_SOCKET,设置SO.SNDTIMEO表示使用发送超时设置,超时时间设置为1000mso
2.构造IP头和TCP头
这里,IP头和TCP头以及TCP伪部的构造
typedefstruct_iphdr
{
UCHARh_lenver;位IP版本号
UCHARtos;
TOS
USHORTtotalJen;
(字节)
USHORTident;
//定义IP首部
//4位首部长度+4
//8位服务类型
//16位总长度
//16位标识
USHORTfrag_and_flags;//3位标志位
UCHARttl;
TTL
UCHARproto;
UDP或其他)
USHORTchecksum;
验和
//8位生存时间
//8位协议(TCP,
//16位IP首部校
ULONGsourcelP;
ULONGdestIP;}IP_HEADER;typedefstructpsd_hdr
//32位源IP地址
//32位目的IP地址
〃定义TCP伪首部
请参考下面它们的数据结构。
USHORTth_sport;
USHORTth_dport;
ULONGth_seq;
ULONGth_ack;
UCHARth_lenres;
位保留字
UCHARth_flag;
USHORTth_win;
USHORTth_sum;
USHORTth_urp;移量
//16位源端口
〃16位目的端口
//32位序列号
//32位确认号
〃4位首部长度/6
//6位标志位
〃16位窗口大小
//16位校验和
//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&Oxffff);
cksum+=(cksum»16);
return(USHORT)(〜cksum);
}
4.流程图
四、调试分析
本程序流程简单,调试过程中没有出现大的问题。
调试过程中没有出现重大的语法错误,主要是运行的结果不理想,和预期的结果有差距。
填充
数据包的程序部分是不容易出错的。
至于数据包的发送,由于是利用函数sendto()来实现的,而sendto()是面向UDP的,将协议类型修改为UDP(Header.proto=IPPROTO_UDP;)后,调试运行成功,问题得到解决。
调试时,要添加
#include
#include
#pragmacomment(lib/*ws2_32・lib'')不然编译出错。
五、使用说明
192.168.1.124200
然后回车,
出现sendok!
输入:
sendtcp192.168.1.123100
表示已经正确发送。
六、源代码
^include〈stdio.h>
#include
ftinclude〈time.h>ftinclude〈windows.h>ttinclude
ttinclude〈stdlib・h>
ftinclude
ttdefineIPVER4
//IP协议预
定
^defineMAX_BUFF_LEN65500//发送缓冲区最大值
UCHARh_verlen;长度,4位IP版本号
UCHARtos;
型TOS
USHORTtotal_len;
(字节)
USHORTident;
USHORTfrag^and^flags;
UCHARttl;
间TTL
UCHARproto;
(TCP,UDP或其他)
USHORTchecksum;校验和
ULONGsourcelP;
//4位首部
//8位服务类
//16位总长度
//16位标识
//3位标志位
//8位生存时
//8位协议
//16位IP首部
//32位源IP
地址
ULONGdestIP;
//32位目的IP
地址
}[P_HEADER;
typedefstructtsd_hdr//定义TCP伪首部
{
ULONGsaddr;//源地址
ULONGdaddr;//目的地址
UCHARmbz;//
UCHARptcl;〃协议类型
USHORTtcpl;//TCP长度
}PSD_HEADER;
typedefstructtcp_hdr//定义TCP首部
//16位源
//16位目
//32位序
//32位确
USHORTth_sport;端口
USHORTth_dport;的端口
ULONGth_seq;列号
ULONGth_ack;
认号
UCHARth_lenres;
长度/6位保留字
UCHARth_flag;志位
USHORTth_win;窗口大小
USHORTth_sum;校验和
USHORTth_urp;紧急数据偏移量
}TCPJEADER;
//4位首部
//6位标
//16位
//16位
//16位
//Checksum:
计算校验和的子函数
USHORTchecksum(USHORT*buffer,intsize){
unsignedlongcksum=0;
while(size>1)
cksum+=*buffer++;size-=sizeof(USHORT);
if(size)
cksum+二*(UCHAR*)buffer;
}
cksum二(cksum»16)+(cksum&Oxffff);
cksum+=(cksum»16);
return(USHORT)Ccksum);
}
intmain(irrtargc,char*argv[])
{
WSADATAWSAData;
SOCKETsock;
IP_HEADERipHeader;
TCP_HEADERtcpHeader;
PSD_HEADERpsdHeader;
charSendto_Buff[MAX_BUFF_LEN];//发送缓冲区
unsignedshort
check_Buff[MAX_BUFF_LEN];//检验和缓冲区
constchartcp_send_data[]二{"Thisismyhomeworkofnetwort,Iamhappy!
"};
BOOLflag;
intrect,nTimeOver;
if(argc!
=5)
{
printf("Useage:
sendtcp
soruce_ipsourcejportdest_ipdest__po:
rt\n");
returnfalse;
if
&WSAData)!
=0)
(WSAStartup(MAKEWORD⑵2),
printf(^WSAStartupError!
\n");
returnfalse;
if((sock二WSASocket(AF_INET,S0CK_RAW,IPPR0T0_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID^SOCKET)
{
printf("SocketSetupError!
\n");returnfalse;
}
flag二true;
〃设置选项值IP_HDRINCL为要设置的选项值
if(setsockopt(sock,IPPR0T0_IP,IP_HDRINCL,(char*)ftflag,sizeof(flag))=S0CKET_ERR0R){
printf("setsockoptIP_HDRINCL
error!
\n");
:
returnfalse;
}
nTime0ver=1000;
〃设置选项值S0_SNDTIME0为要设置的选项值
if(setsockopt(sock,S0L_S0CKET,
SO_SNDTIMEO,(char*)&nTimeOver,
sizeof(nTimeOver))二二SOCKET_ERROR)
{
printf("setsockoptSO_SNDTIMEOerror!
\n/z);
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=IPPR0T0_UDP;〃协议类型
ipHeader.checksum=O:
//检验和暂时为ipHeader・sourcelP二inet_addr(argv[1]);//32位源IP地址
ipHeader・destlP=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・sourcelP;
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)«410);
tcpHeader.th_flag=2;//修改这里来实现不同的标志位探测,2是SYN,1是//FIN,16是ACK探测等等
tcpHeader・th_win=htons((unsigned
tcpHeader・th_urp=0;
//偏移大小
tcpHeader.th_sum=0;
〃检验和暂时填为0
〃计算TCP校验和
memset(check_Buff,0,MAX_BUFF_LEN);
memcpy(check_Buff,ftpsdHeader,sizeof(psdHeader));
memcpy(check_Buff+sizeof(psdHeader),&tcpHeader,sizeof(tcpHeader));
memcpy(check__Buff+sizeof(PSDJHEADER)+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));
int
datasize二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_add:
r(argv[3]);
dest・sin__port二htons(atoi(argv[4]));rect二sendto(sock,Sendto_Buff,datasize,0,(struetsockaddr*)&dest,sizeof(dest));
if(rect==S0CKET_ERR0R)
printf("send
error!
:
%d\n",WSAGetLastError());
returnfalse;
else
printf("sendok!
\n");closesocket(sock);
WSACleanupO;
return1;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络 课程设计 数据包 发送 接受 程序 实现