Windows平台的原始套接字编程的知识点概要(备忘)
原文地址::https://blog.csdn.net/qq_33205982/article/details/54948250 相关文章 1、Linux网络编程——原始套接字实例:MAC 头部报文分析----https://blog.csdn.net/lianghe_work/article/details/45171713 2、Windows下利用原始套接字实现的一个抓包程序Demo----https://blog.csdn.net/kyt511/article/details/45950535
其实从大学学习了C语言后,翻看整本教材只有C语言的语法,根本没有网络编程相关的任何内容,现在回想起来,都记不起自己何时在哪本书上学习了套接字编程,说起TCP、UDP,能知道他们的区别,相关的编程的“套路”,即分别在服务器端和客户端应用程序的固定招数,函数也还是有那么多,但是功能方面嘛,仔细想想,一般除了通信传输数据,文件等,就没有其他目的了,即使有多播,组播,广播等,目的也是为了通信,而且都是在局域网内。以上提到的这些都太中规中矩了,总感觉少了些什么,比如网络性能监视类的程序,网络探测、网络攻击等程序肯定光用这个套接字编程技术无法实现。 写这篇文章是为了温故知新,照着Windows网络编程一书第7章内容而写。所以全手打。 -----------------------分----割----线----------------------------------- 原始套接字是允许访问底层传输协议的一种套接字类型,提供了普通套接字所不具备的功能,能够对网络数据包进行某种程度的控制操作。 原始套接字提供普通套接字不具备的能力有:发送和接收内核不处理其协议字段的IPv4数据包。对于8位IPv4协议字段,大多数内核仅仅处理该字段值为1(ICMP协议)、2(IGMP协议)、6(TCP协议)、17(UDP协议)的数据报,但是协议字段的值还有很多。例如,OSPF路由协议的值为89,如果要处理OSPF数据报文,那么程序必须使用原始套接字读写。 直接总结干货: 首先,在WinSock2中,很熟悉的两个函数:socket()和WSASocket(),第二个参数用常量SOCK_RAW指明,第三个参数IPPROTO_RAW或者IPPROTO_IP 其次,可以不用在原始套接字上调用bind()函数,也可以不用调用connect()函数, 然后,接收数据时可以调用recvfrom()或者WSARecvFrom()函数。 当接收数据时,在接收到一个数据包后,IP协议栈会把满足以下条件的IP数据包传递到原始套接字中: 1、既不是UDP的数据也不是TCP的数据包;2、部分ICMP分组;3、所有的IGMP分组;4、其他所有的IP数据包;5、重组后的分片数据。 传递到原始套接字中的数据包会根据接收条件决定是否拷贝,若满足则拷贝到原始套接字的接收缓冲区中。 假如我们希望能够接收到所有发给网卡的数据,甚至是流经网卡但并非给本机的数据,可以通过设置接收选项SIO_RCVALL就能实现,设置该套接字控制命令则需要通过函数WSAIoctl()。但是比如在设计一个ping程序时,发出请求后接收响应时,很可能有其他的ICMP消息产生干扰,此时就应该从数据来源IP地址,协议类型等方面来判断接收到的数据,正确匹配。 当然了,发送数据时可以调用sendto()或WSASendTo()函数,广播地址,多播地址同样适用(广播或者多播时需要通过setsocketopt()函数设置选项SO_BROADCAST!!) connect()函数指明远端地址。 如果要设置IP首部,IPv4时选项为IP_HDRINCL,选项级别为IPPROTO_IP。当然,此后才能调用bind()函数来指明本机IP地址。要知道,只有这个选项开启了,才能在IP首部中修改源IP地址!可惜Windows对这些作了限制,如果源IP地址不正确,恶意代码不能通过伪造的源IP地址进行拒绝服务攻击,也不能发送IP欺骗数据包。如果原始套接字无法满足需求,还有WInPcap编程直接操控数据帧。 有两个编程示例: 第一个:使用原始套接字实现ping ping是很多操作系统上用来检验主机是否连通网络,以及探测远程主机是否存活的实用工具之一,它通过系那个远程主机发送ICMP协议包并检验取回的远程主机吸纳供应包来实现上述功能。 概念: 位于网络层的IP协议和ICMP协议属于同等级的, 正因为原始套接字才能构造、发送和接收ICMP协议的数据包。ping程序使用了ICMP协议的ECHO类型的请求报文,程序中需要发送ECHO请求和接收响应,并计算间隔时间,判断网络状况。 ECHO请求由ICMP首部和ICMP数据组成,在前面加上IP首部构成IP数据包。即IP数据包=IP首部+ICMP首部+ICMP数据 所以,先定义ICMP首部的结构体,有类型,代码,校验和,ECHO请求的标识,序号5个成员共计8个字节 直接贴代码: 头文件: #pragma pack(1)
源文件: #include <stdio.h> 第二个:使用原始套接字实现的数据包捕获(极简单的统计流量,嗅探器) 仅有一个函数:(伪代码) int _tmain(int argc,_TCHAR* argv[]){WSADATA wsaData; SOCKET SnifferSocket = INVALID_SOCKET; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN;struct hostent *local; char HostName[DEFAULT_NAMELEN];struct in_addr addr;struct sockaddr_in LocalAddr,RemoteAddr;int addrlen = sizeof(struct sockaddr_in);int in=0,i=0;DWORD dwBufferLen[10]; DWORD Optval= 1 ; DWORD dwBytesReturned = 0 ;// 初始化套接字 //创建原始套接字 SnifferSocket = socket ( AF_INET,IPPROTO_IP);//获取本机名称iResult = gethostname( HostName,sizeof(HostName));//获取本机可用IP local = gethostbyname( HostName);printf ("n本机可用的IP地址为:n");while (local->h_addr_list[i] != 0) { addr.s_addr = *(u_long *) local->h_addr_list[i++];printf("tIP Address #%d: %sn",i,inet_ntoa(addr)); } printf ("n请选择捕获数据待使用的接口号:");scanf_s( "%d",&in); memset( &LocalAddr,sizeof(LocalAddr));memcpy( &LocalAddr.sin_addr.S_un.S_addr,local->h_addr_list[in-1],sizeof(LocalAddr.sin_addr.S_un.S_addr));LocalAddr.sin_family = AF_INET;LocalAddr.sin_port=0;//绑定本地地址iResult = bind( SnifferSocket,(struct sockaddr *) &LocalAddr,sizeof(LocalAddr));//设置套接字接收命令iResult = WSAIoctl(SnifferSocket,SIO_RCVALL,&Optval,sizeof(Optval),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL );//开始接收数据 printf(" n开始接收数据");do{//接收数据iResult = recvfrom( SnifferSocket,recvbuf,DEFAULT_BUFLEN,(struct sockaddr *)&RemoteAddr,&addrlen);if (iResult > 0)printf ("n接收到来自%s的数据包,长度为%d.",inet_ntoa(RemoteAddr.sin_addr),iResult );elseprintf("recvfrom failed with error: %ldn",WSAGetLastError());} while(iResult > 0);return 0;} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- [Windows] IIS 7 产生凭证要求文件 (IIS7 Export Certifica
- windows-server-2012-r2 – CentOS cifs客户端将Windows 20
- Windows的管道查看器(`pv`)是否有二进制文件?
- windows – 等待标题时,Docker Toolbox Tutorial Client.Ti
- Window10下Python3.7 安装与卸载
- 使用Win32 API更新许多Windows的Z顺序
- windows-server-2008 – Windows Server 2008和Server 2012
- windows – 无法检索目录列表
- Windows -1252不支持编码名称. C#
- windows-phone-8 – 我可以用什么来替换Windows Phone 8中的
- 获取传递给PowerShell中的函数的所有参数
- windows-server-2008 – 更新Windows服务器
- 在Windows上正确设置OpenSSH的用户权限?
- Windows – TextPad和Unicode:完全支持?
- api – Windows Live Mesh为程序设置提供同步;我
- Windows 8 GUI,以及WPF/SilverLight/WinRT/Metro
- windows – 当请求的缓冲区大小大于可用数据量时
- Windows VC++ 调整进程当前目录为程序可执行文件
- Windows – 如何将多个文件名传递给上下文菜单Sh
- 终端服务 – 如何阻止Windows应用程序窃取焦点