1、 原始套接字的主要功能是什么?
课本(P138)
1) 发送和接收ICMPv4、IGMPv4和ICMPv6等分组;
2) 发送和接收内核不处理其协议字段的IPv4数据包;
3) 控制IPv4首部。
2、 原始套接字的适用场合有哪些?
课本(P139)
1) 特殊用途的探测应用;
2) 基于数据包的捕获应用;
3) 特殊用途的传输应用。
3、 原始套接字的发送内容是否需要包含IP首部?接收的数据是否包含IP首部?
课本(P141、P144)
1) 接收数据的内容
从接收数据的内容来看,不论如何设置发送选项,对于IPv4,原始套接字接收到的数据都是包括IP首部的内在的完整数据包,对于IPv6,原始套接字接收到的都是去掉了IPv6首部和所有扩展首部的净载荷。
2) 发送数据的内容
从发送数据的内容来看,原始套接字的发送内容涉及多种协议首部的构造,对于IPv4(或IPv6)数据的发送,IP首部控制选项为协议首部的填充提供了两个层次的选择:如果是IPv4,选项为IP_HDRINCL,选项级别为IPPROTO_IP;如果是IPv6,选项为IPV6_HDRINCL,选项级别为IPPROTO_IPV6。
当IP首部控制选项未开启,则不需要包含IP首部,IP协议首部由协议栈负责填充;
当IP首部控制选项开启,则需要包含IP协议首部,IP由用户完成构造。
4、 为什么原始套接字的地址结构中的端口可以设置为0?
课本(P144)
从发送数据的目标来看,原始套接字不存在端口号的概念,对于目的地址的描述时,端口是可以忽略的。
5、 SIO_RCVALL命令允许指定的套接字接收所有经过本机的数据。
课本(P143)
6、为什么说TCP的数据不能通过原始套接字发送。
课本(P154)
因为特定的操作系统对原始套接字的功能作出了限制。
7、编写一个最简单的多线程例子程序。
#include
#include
#include
//子线程函数
unsignedint __stdcall ThreadFun(PVOID pM)
{
printf("线程ID号为%4d的子线程说:Hello World\n",GetCurrentThreadId());
return 0;
}
intmain()
{
printf(" 创建多个子线程\n");
printf(" -- by MoreWindows(http://blog.csdn.net/MoreWindows ) --\n\n");
const int THREAD_NUM = 5;
HANDLE handle[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++)
handle[i] = (HANDLE)_beginthreadex(NULL,0, ThreadFun, NULL, 0, NULL);
WaitForMultipleObjects(THREAD_NUM, handle,TRUE, INFINITE);
return 0;
}
8、数据包捕获原理是什么?
课本(P151)
通常得而套接字程序只能响应与自己的MAC地址相匹配的或是以广播的形式发出的数据帧,对于其他形式的数据帧,网络接口采取的动作是直接丢弃。为了使网卡能够接收所有经过它的数据帧,需要将网卡设置为混杂模式。使用SIO_RCVALL命令可以在原始套接字上设置网卡以混杂模式工作,在此基础上从网卡上接收数据和对数据进行解析。
9、函数gethostbyname的作用是什么?
课本(P44)
根据主机名获得主机信息。
参考博客:http://blog.csdn.net/hello_wyq/article/details/1180337
10、请写出ICMP头部checksum的计算程序。
USHORT checksum(USHORT *buffer,int size)
{
unsigned long cksum=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);
}
参考:https://wenku.baidu.com/view/83fc077d168884868762d6ef.html