16.3.5 原始套接字编程(www.cppentry.com)
Windows Socket中的TCP/IP服务提供程序支持原始套接字编程(www.cppentry.com),使用原始套接字可以编写自定义协议格式的套接字。原始套接字包括两种类型,一种是在IP头部分已知协议类型,第二种是实现任意协议的套接字。第一种类型的套接字有ICMP,第二种套接字可以实现服务提供程序不支持的协议。
如果TCP/IP服务提供程序支持AF_INET族的SOCK_RAW套接字,则对应的协议会在WSAEnumProtocols()协议列举函数中返回的列表中存在。如果服务提供程序允许应用程序指定创建套接字函数的protocol参数值为任意值,则WSAPROTOCOL_INFO结构的ipProtocol成员设置为0。而如果使用原始套接字SOCK_RAW,则此参数值不能指定为0。使用原始套接字有以下几方面需要注意。
当应用程序发送数据报时,可以通过设置IP_HDRINCL选项决定是否包含IP头。无论IP_HDRINCL选项的设置是什么,应用程序总是会在接收到的数据报开始部分获取到IP头。当指定了以下条件,则接收到的数据报会全部复制到原始套接字中。
如果套接字指定的协议号与接收到的数据报中的IP头中的协议号一致。
如果定义套接字的本地IP地址与接收到的数据报中的IP头中指定的目的地址一致。
如果套接字定义的外部地址与接收到的数据报中的IP头中指定的目的地址一致。
原始套接字会导致接收到很多不希望处理的数据报。如PING命令使用SOCK_RAW原始套接字发送ICMP回显请求。而当应用程序接收到ICMP回显响应时,其他所有ICMP消息,如ICMP的查询不到主机响应HOST_UNREACHABLE也会发送给应用程序。而且同一时间在同一台机器上打开多个原始套接字,则相同的数据报会发送给所有打开的套接字。应用程序必须能够识别出自己的数据报而忽略到其他原始套接字的数据报,此时需要在IP头中使用唯一的编号类区分。
因此,从上面可以看出,原始套接字是忽略具体协议的底层协议的套接字实现。用户使用原始套接字可以实现数据截获等有关网络底层操作的功能。而要实现与应用程序或指定协议相关的数据通信,建议不要使用原始套接字。原始套接字的编程(www.cppentry.com)与其他套接字的编程(www.cppentry.com)方式是类似的。