原始套接字是一种套接字类型,与流式套接字和用户数据报套接字属于同一级别的概念。
套接字类型是指创建套接字的应用程序要使用的通信服务类型。linux系统支持多种套接字类型,最常用的有以下三种:
(1)SOCK_STREAM:流式套接字,提供面向连接、可靠的数据传输服务,数据按字节流、按顺序收发,保证在传输过程中无丢失、无冗余。TCP协议支持该套接字。
(2)SOCK_DGRAM:数据报套接字,提供面向无连接的服务,数据收发无序,不能保证数据的准确到达。UDP协议支持该套接字。
(3)SOCK_RAW:原始套接字。允许对低于传输层的协议或物理网络直接访问,例如可以接收和发送ICMP报文。常用于检测新的协议。
根据地址域类型的不同,不同的原始套接字有不同的功能
常见的几个这几种原始套接字:
1.ip域原始套接字
int sockfd = 0;
sockfd = socket(PF_INET, SOCK_RAW, int protocol);
我们可以直接实现自行构造整个IP报文,然后对其收发。提醒一点,在用这种方式构造原始IP报文时,第三个参数protocol不能用IPPROTO_IP,这样会让系统疑惑,不知道该用什么协议来伺候你了。
protocol为该套接字对应的协议类型:
/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
#define IPPROTO_IPIP IPPROTO_IPIP
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
#define IPPROTO_TCP IPPROTO_TCP
IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
#define IPPROTO_EGP IPPROTO_EGP
IPPROTO_PUP = 12, /* PUP protocol. */
#define IPPROTO_PUP IPPROTO_PUP
IPPROTO_UDP = 17, /* User Datagram Protocol. */
#define IPPROTO_UDP IPPROTO_UDP
IPPROTO_IDP = 22, /* XNS IDP protocol. */
#define IPPROTO_IDP IPPROTO_IDP
IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */
#define IPPROTO_TP IPPROTO_TP
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
#define IPPROTO_DCCP IPPROTO_DCCP
IPPROTO_IPV6 = 41, /* IPv6 header. */
#define IPPROTO_IPV6 IPPROTO_IPV6
IPPROTO_ROUTING = 43, /* IPv6 routing header. */
#define IPPROTO_ROUTING IPPROTO_ROUTING
IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
IPPROTO_RSVP = 46, /* Reservation Protocol. */
#define IPPROTO_RSVP IPPROTO_RSVP
IPPROTO_GRE = 47, /* General Routing Encapsulation. */
#define IPPROTO_GRE IPPROTO_GRE
IPPROTO_ESP = 50, /* encapsulating security payload. */
#define IPPROTO_ESP IPPROTO_ESP
IPPROTO_AH = 51, /* authentication header. */
#define IPPROTO_AH IPPROTO_AH
IPPROTO_ICMPV6 = 58, /* ICMPv6. */
#define IPPROTO_ICMPV6 IPPROTO_ICMPV6
IPPROTO_NONE = 59, /* IPv6 no next header. */
#define IPPROTO_NONE IPPROTO_NONE
IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
#define IPPROTO_MTP IPPROTO_MTP
IPPROTO_ENCAP = 98, /* Encapsulation Header. */
#define IPPROTO_ENCAP IPPROTO_ENCAP
IPPROTO_PIM = 103, /* Protocol Independent Multicast. */
#define IPPROTO_PIM IPPROTO_PIM
IPPROTO_COMP = 108, /* Compression Header Protocol. */
#define IPPROTO_COMP IPPROTO_COMP
IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
#define IPPROTO_SCTP IPPROTO_SCTP
IPPROTO_UDPLITE = 136, /* UDP-Lite protocol. */
#define IPPROTO_UDPLITE IPPROTO_UDPLITE
IPPROTO_RAW = 255, /* Raw IP packets. */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MAX
};
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <errno.h>
-
#include <string.h>
-
#include <unistd.h>
-
#include <netdb.h>
-
#include <sys/socket.h>
-
#include <sys/types.h>
-
#include <netinet/in.h>
-
#include <netinet/ip.h>
-
#include <arpa/inet.h>
-
#include <linux/tcp.h>
-
-
-
-
int main(int argc, char **argv)
-
{
-
int sockfd = 0;
-
char buffer[1024] = { 0 };
-
int len = 0;
-
int i = 0;
-
-
/* ptotocol can't is IPPROTO_IP(0)*/
-
sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
-
if(sockfd < 0)
-
{
-
printf("%d \n", sockfd);
-
perror("socket");
-
exit(0);
-
}
-
-
while(1)
-
{
-
memset(buffer, 0, sizeof(buffer));
-
len = recv(sockfd, buffer, sizeof(buffer), 0);
-
if(len < 0)
-
{
-
perror("recv");
-
exit(0);
-
}
-
-
printf("\nrecv pkt len = %d\n", len);
-
for(i = 0; i < len; i++)
-
{
-
printf(" %02X", buffer[i]);
-
if(0 == i%16)
-
{
-
printf("\n");
-
}
-
-
}
-
-
printf("\n");
-
}
-
}
阅读(1793) | 评论(0) | 转发(0) |