c++的socket编程相关资料汇总.docx
- 文档编号:571573
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:65
- 大小:88.17KB
c++的socket编程相关资料汇总.docx
《c++的socket编程相关资料汇总.docx》由会员分享,可在线阅读,更多相关《c++的socket编程相关资料汇总.docx(65页珍藏版)》请在冰点文库上搜索。
c++的socket编程相关资料汇总
1、原始套接字透析之前言2
2、TCP/UDP完整数据包校验和通用计算8
3、使用原始套接字发送自定义IP包13
4、VisualC++自定义发IP包例子21
5、Win2000中用户自定义IP头的实现及OicqSend完整实例源程序25
6、一个syn扫描程序源代码32
7、穿透防火墙的数据传输源码41
1、原始套接字透析之前言
大多数程序员所接触到的套接字(Socket)为两类:
(1)流式套接字(SOCK_STREAM):
一种面向连接的Socket,针对于面向连接的TCP服务应用;
(2)数据报式套接字(SOCK_DGRAM):
一种无连接的Socket,对应于无连接的UDP服务应用。
从用户的角度来看,SOCK_STREAM、SOCK_DGRAM这两类套接字似乎的确涵盖了TCP/IP应用的全部,因为基于TCP/IP的应用,从协议栈的层次上讲,在传输层的确只可能建立于TCP或UDP协议之上(图1),而SOCK_STREAM、SOCK_DGRAM又分别对应于TCP和UDP,所以几乎所有的应用都可以用这两类套接字实现。
图1TCP/IP协议栈
但是,当我们面对如下问题时,SOCK_STREAM、SOCK_DGRAM将显得这样无助:
(1)怎样发送一个自定义的IP包?
(2)怎样发送一个ICMP协议包?
(3)怎样使本机进入杂糅模式,从而能够进行网络sniffer?
(4)怎样分析所有经过网络的包,而不管这样包是否是发给自己的?
(5)怎样伪装本地的IP地址?
这使得我们必须面对另外一个深刻的主题――原始套接字(RawSocket)。
RawSocket广泛应用于高级网络编程,也是一种广泛的黑客手段。
著名的网络sniffer、拒绝服务攻击(DOS)、IP欺骗等都可以以RawSocket实现。
RawSocket与标准套接字(SOCK_STREAM、SOCK_DGRAM)的区别在于前者直接置"根"于操作系统网络核心(NetworkCore),而SOCK_STREAM、SOCK_DGRAM则"悬浮"于TCP和UDP协议的外围,如图2所示:
图2RawSocket与标准Socket
当我们使用RawSocket的时候,可以完全自定义IP包,一切形式的包都可以"制造"出来。
因此,本文事先必须对TCP/IP所涉及IP包结构进行必要的交待。
目前,IPv4的报头结构为:
版本号(4)
包头长(4)
服务类型(8)
数据包长度(16)
标识(16)
偏移量(16)
生存时间(8)
传输协议(8)
校验和(16)
源地址(32)
目的地址(32)
选项(8)
.........
填充
对其进行数据结构封装:
typedefstruct_iphdr//定义IP报头
{
unsignedcharh_lenver;//4位首部长度+4位IP版本号
unsignedchartos;//8位服务类型TOS
unsignedshorttotal_len;//16位总长度(字节)
unsignedshortident;//16位标识
unsignedshortfrag_and_flags;//3位标志位
unsignedcharttl;//8位生存时间TTL
unsignedcharproto;//8位协议(TCP,UDP或其他)
unsignedshortchecksum;//16位IP首部校验和
unsignedintsourceIP;//32位源IP地址
unsignedintdestIP;//32位目的IP地址
}IP_HEADER;
或者将上述定义中的第一字节按位拆分:
typedefstruct_iphdr//定义IP报头
{
unsignedcharh_len:
4;//4位首部长度
unsignedcharver:
4;//4位IP版本号
unsignedchartos;
unsignedshorttotal_len;
unsignedshortident;
unsignedshortfrag_and_flags;
unsignedcharttl;
unsignedcharproto;
unsignedshortchecksum;
unsignedintsourceIP;
unsignedintdestIP;
}IP_HEADER;
更加严格地讲,上述定义中h_len、ver字段的内存存放顺序还与具体CPU的Endian有关,因此,更加严格的IP_HEADER可定义为:
typedefstruct_iphdr//定义IP报头
{
#ifdefined(__LITTLE_ENDIAN_BITFIELD)
unsignedcharh_len:
4;//4位首部长度
unsignedcharver:
4;//4位IP版本号
#elifdefined(__BIG_ENDIAN_BITFIELD)
unsignedcharver:
4;//4位IP版本号
unsignedcharh_len:
4;//4位首部长度
#endif
unsignedchartos;
unsignedshorttotal_len;
unsignedshortident;
unsignedshortfrag_and_flags;
unsignedcharttl;
unsignedcharproto;
unsignedshortchecksum;
unsignedintsourceIP;
unsignedintdestIP;
}IP_HEADER;
TCP报头结构为:
源端口(16)
目的端口(16)
序列号(32)
确认号(32)
TCP偏移量(4)
保留(6)
标志(6)
窗口(16)
校验和(16)
紧急(16)
选项(0或32)
数据(可变)
对应数据结构:
typedefstructpsd_hdr//定义TCP伪报头
{
unsignedlongsaddr;//源地址
unsignedlongdaddr;//目的地址
charmbz;
charptcl;//协议类型
unsignedshorttcpl;//TCP长度
}PSD_HEADER;
typedefstruct_tcphdr//定义TCP报头
{
unsignedshortth_sport;//16位源端口
unsignedshortth_dport;//16位目的端口
unsignedintth_seq;//32位序列号
unsignedintth_ack;//32位确认号
unsignedcharth_lenres;//4位首部长度/4位保留字
unsignedcharth_flag;//6位标志位
unsignedshortth_win;//16位窗口大小
unsignedshortth_sum;//16位校验和
unsignedshortth_urp;//16位紧急数据偏移量
}TCP_HEADER;
同样地,TCP头的定义也可以将位域拆分:
typedefstruct_tcphdr
{
unsignedshortth_sport;
unsignedshortth_dport;
unsignedintth_seq;
unsignedintth_ack;
/*little-endian*/
unsignedshorttcp_res1:
4,tcp_hlen:
4,tcp_fin:
1,tcp_syn:
1,tcp_rst:
1,tcp_psh:
1,tcp_ack:
1,tcp_urg:
1,tcp_res2:
2;
unsignedshortth_win;
unsignedshortth_sum;
unsignedshortth_urp;
}TCP_HEADER;
UDP报头为:
源端口(16)
目的端口(16)
报文长(16)
校验和(16)
对应的数据结构为:
typedefstruct_udphdr//定义UDP报头
{
unsignedshortuh_sport;//16位源端口
unsignedshortuh_dport;//16位目的端口
unsignedshortuh_len;//16位长度
unsignedshortuh_sum;//16位校验和
}UDP_HEADER;
ICMP协议是网络层中一个非常重要的协议,其全称为InternetControlMessageProtocol(因特网控制报文协议),ICMP协议弥补了IP的缺限,它使用IP协议进行信息传递,向数据包中的源端节点提供发生在网络层的错误信息反馈。
ICMP报头为:
类型(8)
代码(8)
校验和(16)
消息内容
常用的回送与或回送响应ICMP消息对应数据结构为:
typedefstruct_icmphdr//定义ICMP报头(回送与或回送响应)
{
unsignedchari_type;//8位类型
unsignedchari_code;//8位代码
unsignedshorti_cksum;//16位校验和
unsignedshorti_id;//识别号(一般用进程号作为识别号)
unsignedshorti_seq;//报文序列号
unsignedinttimestamp;//时间戳
}ICMP_HEADER;
常用的ICMP报文包括ECHO-REQUEST(响应请求消息)、ECHO-REPLY(响应应答消息)、DestinationUnreachable(目标不可到达消息)、TimeExceeded(超时消息)、ParameterProblems(参数错误消息)、SourceQuenchs(源抑制消息)、Redirects(重定向消息)、Timestamps(时间戳消息)、TimestampReplies(时间戳响应消息)、AddressMasks(地址掩码请求消息)、AddressMaskReplies(地址掩码响应消息)等,是Internet上十分重要的消息。
后面章节中所涉及到的ping命令、ICMP拒绝服务攻击、路由欺骗都与ICMP协议息息相关。
另外,本系列文章中的部分源代码参考了一些优秀程序员的开源项目,由于篇幅的关系我们不能一一列举,在此一并表示感谢。
本文来自CSDN博客,转载请标明出处:
2、TCP/UDP完整数据包校验和通用计算
2009-03-2317:
18:
13| 分类:
c++学习阅读388评论0 字号:
大中小 订阅
经验]TCP,UDP完整数据包校验和通用计算
ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。
ICMP和IP报头校验和的计算都很简单,使用RFC1071中给出的方法即可完成(如下)。
//计算校验和
USHORTchecksum(USHORT*buffer,intsize)
{
unsignedlongcksum=0;
while(size>1)
{
cksum+=*buffer++;
size-=sizeof(USHORT);
}
if(size)
{
cksum+=*(UCHAR*)buffer;
}
//将32位数转换成16
while(cksum>>16)
cksum=(cksum>>16)+(cksum&0xffff);
return(USHORT)(~cksum);
}
UDP/TCP报头中的校验和的计算比较复杂的,要用到UDP/TCP伪首部:
先要填充伪首部各个字段,然后再将UDP/TCP报头以后(包括报头)的数据附加到伪首部的后面,再对位首部使用上述校验和计算,所得到的值才是UDP/TCP报头部分的校验和。
位首部可以用如下的结构体表示:
typedefstruct{
ULONG sourceip; //源IP地址
ULONG destip; //目的IP地址
BYTEmbz; //置空(0)
BYTEptcl; //协议类型
USHORTplen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度单位:
字节)
}Psd_Header;
这个过程是一个很繁琐的过程,计算过几次后再也忍受不了做这样重复的工作,于是写了一个通用的计算函数。
这个函数使用起来我感觉非常方便:
先封装好你的数据包(完整的,包括以太头),然后将数据包的首地址作为参数,调用该函数即可。
函数将帮你完成IP报头以及UDP/TCP报头部分校验和的计算。
//-------------------------------------------------------------------------
//PacketCheckSum
//计算数据包的校验和
//参数:
packet-待处理数据(将封装好的数据包的指针)
//-------------------------------------------------------------------------
voidPacketCheckSum(unsignedcharpacket[])
{
Dlc_Header*pdlc_header=NULL;//以太头指针
Ip_Header *pip_header=NULL; //IP头指针
unsignedshortattachsize=0;//传输层协议头以及附加数据的总长度
pdlc_header=(Dlc_Header*)packet;
//判断ethertype,如果不是IP包则不予处理
if(ntohs(pdlc_header->ethertype)!
=0x0800)return;
pip_header=(Ip_Header *)(packet+14);
//TCP包
if(0x06==pip_header->proto)
{
Tcp_Header*ptcp_header=NULL;//TCP头指针
Tcp_Psd_Header*ptcp_psd_header=NULL;
ptcp_header=(Tcp_Header*)(packet+14+((pip_header->ver_len)&15)*4);
attachsize=ntohs(pip_header->total_len)-((pip_header->ver_len)&15)*4;
ptcp_psd_header=(Tcp_Psd_Header*)malloc(attachsize+sizeof(Tcp_Psd_Header));
if(!
ptcp_psd_header)return;
memset(ptcp_psd_header,0,attachsize+sizeof(Tcp_Psd_Header));
//填充伪TCP头
ptcp_psd_header->destip=pip_header->destIP;
ptcp_psd_header->sourceip=pip_header->sourceIP;
ptcp_psd_header->mbz=0;
ptcp_psd_header->ptcl=0x06;
ptcp_psd_header->tcpl=htons(attachsize);
//计算TCP校验和
ptcp_header->chksum=0;
memcpy((unsignedchar*)ptcp_psd_header+sizeof(Tcp_Psd_Header),
(unsignedchar*)ptcp_header,attachsize);
ptcp_header->chksum=checksum((unsignedshort*)ptcp_psd_header,
attachsize+sizeof(Tcp_Psd_Header));
//计算ip头的校验和
pip_header->checksum=0;
pip_header->checksum=checksum((unsignedshort*)pip_header,20);
return;
}
//UDP包
if(0x11==pip_header->proto)
{
Udp_Header*pudp_header=NULL;//UDP头指针
Udp_Psd_Header*pudp_psd_header=NULL;
pudp_header=(Udp_Header*)(packet+14+((pip_header->ver_len)&15)*4);
attachsize=ntohs(pip_header->total_len)-((pip_header->ver_len)&15)*4;
pudp_psd_header=(Udp_Psd_Header*)malloc(attachsize+sizeof(Udp_Psd_Header));
if(!
pudp_psd_header)return;
memset(pudp_psd_header,0,attachsize+sizeof(Udp_Psd_Header));
//填充伪UDP头
pudp_psd_header->destip=pip_header->destIP;
pudp_psd_header->sourceip=pip_header->sourceIP;
pudp_psd_header->mbz=0;
pudp_psd_header->ptcl=0x11;
pudp_psd_header->udpl=htons(attachsize);
//计算UDP校验和
pudp_header->chksum=0;
memcpy((unsignedchar*)pudp_psd_header+sizeof(Udp_Psd_Header),
(unsignedchar*)pudp_header,attachsize);
pudp_header->chksum=checksum((unsignedshort*)pudp_psd_header,
attachsize+sizeof(Udp_Psd_Header));
//计算ip头的校验和
pip_header->checksum=0;
pip_header->checksum=checksum((unsignedshort*)pip_header,20);
return;
}
return;
}
需要几个头文件,以及库:
#include
#include
#include"packet.h"
#pragmacomment(lib,"ws2_32.lib")
最后附上我使用的数据包的结构体(比较多):
//数据包结构体
#pragmapack
(1)
/*物理帧头结构*/
typedefstruct{
BYTE desmac[6]; //目的MAC地址
BYTE srcmac[6]; //源MAC地址
USHORT ethertype; //帧类型
}Dlc_Header;
/*Arp帧结构*/
typedefstruct{
USHORThw_type; //硬件类型Ethernet:
0x1
USHORTprot_type; //上层协议类型IP:
0x0800
BYTEhw_addr_len; //硬件地址长度:
6
BYTEprot_addr_len; //协议地址(IP地址)的长度:
4
USHORTflag; //1表示请求,2表示应答
BYTEsend_hw_addr[6];//源MAC地址
UINTsend_prot_addr; //源IP地址
BYTEtarg_hw_addr[6];//目的MAC地址
UINTtarg_prot_addr; //目的IP地址
BYTEpadding[18]; //填充数据
}Arp_Frame;
/*ARP包=DLC头+ARP帧*/
typedefstruct{
Dlc_Headerdlcheader;//DLC头
Arp_Framearpframe; //ARP帧
}ARP_Packet;
/*IP报头结构*/
typedefstruct{
BYTE ver_len; //IP包头部长度,单位:
4字节
BYTE tos; //服务类型TOS
USHORTtotal_len; //IP包总长度
USHORTident; //标识
USHORTfrag_and_flags; //标志位
BYTEttl; //生存时间
BYTEproto; //协议
USHORTchecksum; //IP首部校验和
UINT sourceIP; //源IP地址(32位)
UINT destIP; //目的IP地址(32位)
}Ip_Header;
/*TCP报头结构*/
typedefstruct{
USHORTsrcport; //源端口
USHORTdstport; //目的端口
UINTse
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c+ socket 编程 相关 资料 汇总