Socket详解-socket建立

Socket建立 



  为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为: 
  int socket(int domain, int type, int protocol); 

 1,domain指明所使用的协议族,


通常为PF_INET,表示互联网协议族(TCP/IP协议族);或者PF_PACKET协议栈( 底层数据包接口)

所以在windows中AF_INET与PF_INET完全一样. 而在Unix/Linux系统中,在不同的版本中这两者有微小差别.对于BSD,是AF,对于POSIX是PF.

理论上建立socket时是指定协议,应该用PF_xxxx,设置地址时应该用AF_xxxx。当然AF_INET和PF_INET的值是相同的,混用也不会有太大的问题。

在函数socketpair与socket的domain参数中有AF_UNIX,AF_LOCAL,AF_INET,PF_UNIX,PF_LOCAL,PF_INET.
这几个参数有AF_UNIX=AF_LOCAL, PF_UNIX=PF_LOCAL, AF_LOCAL=PF_LOCAL, AF_INET=PF_INET.

Socket数据结构中包含这五种信息。

第一个参数family指的是协议族(或者说协议栈)。主要的协议族有以下:

PF_INET             互联网IPv4

PF_IPX                IPX协议

PF_NETLINK     一个用户空间和内核的接口

PF_PACKET       底层数据包接口

源代码有所有协议栈库在 系统函数库

[html]  view plain  copy
  1. /usr/include/bits/socket.h  
  2.    
  3.     73 /* Protocol families.  */  
  4.      74 #define PF_UNSPEC       0       /* Unspecified.  */  
  5.      75 #define PF_LOCAL        1       /* Local to host (pipes and file-domain).  */  
  6.      76 #define PF_UNIX         PF_LOCAL /* POSIX name for PF_LOCAL.  */  
  7.      77 #define PF_FILE         PF_LOCAL /* Another non-standard name for PF_LOCAL.  */  
  8.      78 #define PF_INET         2       /* IP protocol family.  */  
  9.      79 #define PF_AX25         3       /* Amateur Radio AX.25.  */  
  10.      80 #define PF_IPX          4       /* Novell Internet Protocol.  */  
  11.      81 #define PF_APPLETALK    5       /* Appletalk DDP.  */  
  12.      82 #define PF_NETROM       6       /* Amateur radio NetROM.  */  
  13.      83 #define PF_BRIDGE       7       /* Multiprotocol bridge.  */  
  14.      84 #define PF_ATMPVC       8       /* ATM PVCs.  */  
  15.      85 #define PF_X25          9       /* Reserved for X.25 project.  */  
  16.      86 #define PF_INET6        10      /* IP version 6.  */  
  17.      87 #define PF_ROSE         11      /* Amateur Radio X.25 PLP.  */  
  18.      88 #define PF_DECnet       12      /* Reserved for DECnet project.  */  
  19.      89 #define PF_NETBEUI      13      /* Reserved for 802.2LLC project.  */  
  20.      90 #define PF_SECURITY     14      /* Security callback pseudo AF.  */  
  21.      91 #define PF_KEY          15      /* PF_KEY key management API.  */  
  22.      92 #define PF_NETLINK      16  
  23.      93 #define PF_ROUTE        PF_NETLINK /* Alias to emulate 4.4BSD.  */  
  24.      94 #define PF_PACKET       17      /* Packet family.  */  
  25.      95 #define PF_ASH          18      /* Ash.  */  
  26.      96 #define PF_ECONET       19      /* Acorn Econet.  */  
  27.      97 #define PF_ATMSVC       20      /* ATM SVCs.  */  
  28.      98 #define PF_RDS          21      /* RDS sockets.  */  
  29.      99 #define PF_SNA          22      /* Linux SNA Project */  
  30.     100 #define PF_IRDA         23      /* IRDA sockets.  */  
  31.     101 #define PF_PPPOX        24      /* PPPoX sockets.  */  
  32.     102 #define PF_WANPIPE      25      /* Wanpipe API sockets.  */  
  33.     103 #define PF_LLC          26      /* Linux LLC.  */  
  34.     104 #define PF_CAN          29      /* Controller Area Network.  */  
  35.     105 #define PF_TIPC         30      /* TIPC sockets.  */  
  36.     106 #define PF_BLUETOOTH    31      /* Bluetooth sockets.  */  
  37.     107 #define PF_IUCV         32      /* IUCV sockets.  */  
  38.     108 #define PF_RXRPC        33      /* RxRPC sockets.  */  
  39.     109 #define PF_ISDN         34      /* mISDN sockets.  */  
  40.     110 #define PF_PHONET       35      /* Phonet sockets.  */  
  41.     111 #define PF_IEEE802154   36      /* IEEE 802.15.4 sockets.  */  
  42.     112 #define PF_CAIF         37      /* CAIF sockets.  */  
  43.     113 #define PF_ALG          38      /* Algorithm sockets.  */  
  44.     114 #define PF_MAX          39      /* For now..  */  
  45.           /*       *   Protocol   families,   same   as   address   families   for   now.     
  46. PF=AF    */ /* Address families.  */  
  47. #define AF_UNSPEC       PF_UNSPEC  
  48. #define AF_LOCAL        PF_LOCAL  
  49. #define AF_UNIX         PF_UNIX  
  50. #define AF_FILE         PF_FILE  
  51. #define AF_INET         PF_INET  
  52. #define AF_AX25         PF_AX25  
  53. #define AF_IPX          PF_IPX  
  54. #define AF_APPLETALK    PF_APPLETALK  
  55. #define AF_NETROM       PF_NETROM  
  56. #define AF_BRIDGE       PF_BRIDGE  
  57. #define AF_ATMPVC       PF_ATMPVC  
  58. #define AF_X25          PF_X25  
  59. #define AF_INET6        PF_INET6  
  60. #define AF_ROSE         PF_ROSE  
  61. #define AF_DECnet       PF_DECnet  
  62. #define AF_NETBEUI      PF_NETBEUI  
  63. #define AF_SECURITY     PF_SECURITY  
  64. #define AF_KEY          PF_KEY  
  65. #define AF_NETLINK      PF_NETLINK  
  66. #define AF_ROUTE        PF_ROUTE  
  67. #define AF_PACKET       PF_PACKET  
  68. #define AF_ASH          PF_ASH  
  69. #define AF_ECONET       PF_ECONET  
  70. #define AF_ATMSVC       PF_ATMSVC  
  71. #define AF_RDS          PF_RDS  
  72. #define AF_SNA          PF_SNA  
  73. #define AF_IRDA         PF_IRDA  
  74. #define AF_PPPOX        PF_PPPOX  
  75. #define AF_WANPIPE      PF_WANPIPE  
  76. #define AF_LLC          PF_LLC  
  77. #define AF_CAN          PF_CAN  
  78. #define AF_TIPC         PF_TIPC  
  79. #define AF_BLUETOOTH    PF_BLUETOOTH  
  80. #define AF_IUCV         PF_IUCV  
  81. #define AF_RXRPC        PF_RXRPC  
  82. #define AF_ISDN         PF_ISDN  
  83. #define AF_PHONET       PF_PHONET  
  84. #define AF_IEEE802154   PF_IEEE802154  
  85. #define AF_CAIF         PF_CAIF  
  86. #define AF_ALG          PF_ALG  
  87. #define AF_MAX          PF_MAX  




2,type参数指定socket的类型:


SOCK_STREAM(tcp) 或SOCK_DGRAM(udp),Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;

linux2.6内核

[html]  view plain  copy
  1. /* Types of sockets.  */  
  2. enum __socket_type  
  3. {  
  4.   SOCK_STREAM = 1,              tcp/* Sequenced, reliable, connection-based  
  5.   SOCK_DGRAM = 2,              udp /* Connectionless, unreliable datagrams  
  6.   SOCK_RAW = 3,                 ip/* Raw protocol interface.  */  
  7.   SOCK_RDM = 4,                 /* Reliably-delivered messages.  */  
  8.   SOCK_SEQPACKET = 5,           /* Sequenced, reliable, connection-based, datagrams of fixed maximum length.  */  
  9.   SOCK_DCCP = 6,                /* Datagram Congestion Control Protocol.  */  
  10.   SOCK_PACKET = 10,             /* Linux specific way of getting packets at the dev level.  For writing rarp and other similar things on the user level. */  
  11.   /* Flags to be ORed into the type parameter of socket and socketpair and  
  12.      used for the flags parameter of paccept.  */  
  13.   
  14.   SOCK_CLOEXEC = 02000000,      /* Atomically set close-on-exec flag for thenew descriptor(s).  */  
  15.   SOCK_NONBLOCK = 04000         /* Atomically mark descriptor(s) as  
  16.                                    non-blocking.  */  
  17. };  



3,protocol通常赋值"0"或者IPPROTO_IP。IPPROTO_IP=0


Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。 

Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立一个Socket"意味着为一个Socket数据结构分配存储空间。Socket执行体为你管理描述符表。

协议类型常用有四个在socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

ETH_P_IP 0x0800          只接收发往本机mac的ip类型的数据帧  

ETH_P_ARP 0x0806     只接受发往本机mac的arp类型的数据帧 

ETH_P_RARP 0x8035  只接受发往本机mac的rarp类型的数据帧 

ETH_P_ALL 0x0003      接收发往本机mac的所有类型ip arp rarp的数据帧, 接收从本机发出的所有类型的数据帧.(混杂模式打开的情况下,会接收到非发往本地mac的数据帧)

在socket(AF_INET, SOCK_RAW,IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)下有

/* Standard well-defined IP protocols. */

enum

{

IPPROTO_IP = 0, /* Dummy protocol for TCP. */

IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */

IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */

IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */

IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */

IPPROTO_TCP = 6, /* Transmission Control Protocol. */

IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */

IPPROTO_PUP = 12, /* PUP protocol. */

IPPROTO_UDP = 17, /* User Datagram Protocol. */

IPPROTO_IDP = 22, /* XNS IDP protocol. */

IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */

IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */

IPPROTO_IPV6 = 41, /* IPv6 header. */

IPPROTO_ROUTING = 43, /* IPv6 routing header. */

IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */

IPPROTO_RSVP = 46, /* Reservation Protocol. */

IPPROTO_GRE = 47, /* General Routing Encapsulation. */#define IPPROTO_GRE IPPROTO_GRE

IPPROTO_ESP = 50, /* encapsulating security payload. */

IPPROTO_AH = 51, /* authentication header. */

IPPROTO_ICMPV6 = 58, /* ICMPv6. */

IPPROTO_NONE = 59, /* IPv6 no next header. */#define IPPROTO_NONE IPPROTO_NONE

IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */

IPPROTO_MTP = 92, /* Multicast Transport Protocol. */

IPPROTO_ENCAP = 98, /* Encapsulation Header. */

IPPROTO_PIM = 103, /* Protocol Independent Multicast. */

eg

sock_raw原始套接字编程可以接收到本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的.一共可以有3种方式创建这种socket

1.socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)发送接收ip数据包

能:该套接字可以接收和发送协议类型为(tcp udp icmp等)发往本机的ip数据包,不包括mac地址. 

  不能:不能收到非发往本地ip的数据包(ip软过滤会丢弃这些不是发往本机ip的数据包). 

不能:不能收到从本机发送出去的数据包. 

不能:不能修改mac地址。数据包是网络层不等于数据帧,不包括mac地址,数据帧是链路层的,包括mac地址。

  发送的话需要自己组织tcp udp icmp等头部.可以setsockopt来自己包装ip头部,这种套接字用来写个ping程序比较适合

2.socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))发送接收以太网数据帧

  能: 接收发往本地mac的数据帧 

  能: 接收从本机发送出去的数据帧(第3个参数需要设置为ETH_P_ALL) 

  能: 接收非发往本地mac的数据帧(网卡需要设置为promisc混杂模式)

3.socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))发送接收以太网数据帧(过时了,不要用啊)

(SOCK_PACKET 方式使用结构 sockaddr_pkt来保存数据链路层信息,但该结构缺乏包类型信息;其次,如果参数 MSG_TRUNC 传递给读包函数recvmsg()、recv()、recvfrom()等,则函数返回的数据包长度是实际读到的包数据长度,而不是数据包真正的长度。Libpcap 的开发者在源代码中明确建议不使用 2.0,http://www.cnblogs.com/huyc/archive/2011/10/19/2217134.html)


  两个网络程序之间的一个网络连接包括五种信息:

通信协议、

本地协议地址、

本地主机端口、

远端主机地址

远端协议端口。

想想会有哪种协议类型是IPPROTO_IP =0的呢?内核使用IPPROTO_IP仅仅是为了在某些情况下默认匹配协议类型而已。例如SOCK_DGRAM协议族默认的协议是

IPPROTO_UDP,SOCK_STREAM默认的是IPPROTO_TCP。即 


socket(PF_INET,SOCK_DGRAM,IPPROTO_IP) 和 
socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)是一样的, 

socket(PF_INET,SOCK_STREAM,IPPROTO_IP) 和 
socket(PF_INET,SOCK_DGRAM,IPPROTO_TCP)一样。 

但是 
socket(PF_INET,SOCK_RAW,IPPROTO_IP)让SOCK_RAW如何选择默认的协议类型呢? 

SOCK_RAW是网络层(IP层)的,而SOCK_PACKET是数据链路层的.一般的UNIX标准(POSIX)
只有SOCK_RAW,SOCK_PACKET是linux专有的,并不通用.SOCK_PACKET和同类实现相比,比较
底层但不实用.具体的请参考<<UNIX Network Programming>>一书 

AF_PACKET是专门用来处理raw socket的,符合我上面列举的规则
是否可以这样总结raw socket的用法:
(1):如果想单独处理TCP,UDP或者ICMP,可用AF_INET, 第三个参数用IPPROTO_TCP, IPPROTO_UDP等

socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)
(2):如果想对各种IP包进行处理,则用AF_PACKET/PF_PACKET,第三个参数用htons(ETH_P_IP)

socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))
(3):如果想处理一切链路层上的包(IP,RARP,ARP等),则用AF_PACKET/PF_PACKET,第三个参数用 htons(ETH_P_ALL) 

socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

1,能接收和发送带mac地址的数据包


socket(PF_PACKET,SOCK_DGRAM,htons(ETH_P_IP))


2,能接收和发送不带mac地址的数据包

(1)udp包

1)socket(PF_INET,SOCK_DGRAM,IPPROTO_IP) 和 
socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)是一样的, 
socket(AF_INET,SOCK_DGRAM,0);也是一样的 

3)socket(AF_INET, SOCK_RAW, IPPROTO_UDP);


(2)tcp包
socket(PF_INET,SOCK_STREAM,IPPROTO_IP) 和 
socket(PF_INET,SOCK_DGRAM,IPPROTO_TCP)一样。 

socket(PF_PACKET,SOCK_DGRAM,htons(ETH_P_IP)) 

PF_PACKET介绍:


在LINUX内核版本中(2.0 releases),一个名为PF_PACKET的协议簇被加了进来!这个簇允许应用程序直接利用网络驱动程序发送和接收报文,避免了原来的协议栈处理过程,在这种情况下,所有SOCKET发出的报文直接送到以太网卡接口,而接口收到的任何报文将直接送到应用程序

The PF_PACKET协议簇支持两个稍微有点不同的SOCKET类型,SOCK_DGRAM和SOCK_RAW。前者让内核处理添加或者去除以太网报文头部工作,而后者则让应用程序对以太网报文头部有完全的控制!在SOCKET调用中的协议类型必须符合/usr/include/linux/if_ether.h中定义的以太网IDs中的一个,除非遇到特别声明的协议,一般你可以用ETH_P_IP来处理IP的一组协议(TCP,UDP,ICMP,raw IP等等)因为它们容易受到一些很严重的安全问题的牵连(比如你可以伪造一个MAC地址),所以只有具有root权限才可以使用PF_PACKET-family socket.这也就是为什么只有具有root权限后才能运行嗅探器的原因!

http://www.cnblogs.com/jinrize/archive/2009/11/24/1609902.html

LPF介绍


LINUX的内核允许我们把一个名为LPF(Linux Packet Filter)的过滤器直接放到PF_PACKET protocol-processing routines(在网卡接收中断执行后立即执行)中,过滤器将决定哪些包被送到应用程序,哪些包被丢弃!这个过滤程序可以根据使用者的定义来运行,由BPF伪机器码写成的。

这个过滤器也不是总是有效的,因为它产生于一般的使用BPF的机器,没考虑到一些特殊结构的机器!在一些特殊情况下,过滤器由PF_PACKET进程运行,也许已经检查过以太协议了!这个根据你在socket()调用初使化的时候指定的那些协议!如果不是ETH_P_ALL(抓所有的报文),那么只有那些符合指定的协议类型的报文会流过过滤器! LPF和BPF的实现不一样。不是一个程序。

BPF介绍:


BPF(BSD Packet Filter)包过滤机制,BPF 于 1992 年被设计出来,其设计目的主要是解决当时已存在的过滤机制效率低下的问题。BPF的工作步骤如下:当一个数据包到达网络接口时,数据链路层的驱动会把它向系统的协议栈传送。但如果 BPF 监听接口,驱动首先调用 BPF。BPF 首先进行过滤操作,然后把数据包存放在过滤器相关的缓冲区中,最后设备驱动再次获得控制。注意到BPF是先对数据包过滤再缓冲,避免了类似 sun 的 NIT 过滤机制先缓冲每个数据包直到用户读数据时再过滤所造成的效率问题。参考资料D是关于 BPF 设计思想最重要的文献。

libpcap提供的一个最有用的函数是pcap_compile(), 它可以把一个输入输出的逻辑表达式变为BPF代码!tcpdump利用这个函数完成在用户输入的命令行和BPF代码之间的转换!tcpdump有个我们很感兴趣但是很少使用的参数 ,-d,可以输出BPF代码!把tcpdump -d中的-d换成-dd,将显示出一段C代码,可以把它复制到自己的程序中,可以通过调用setsockopt()来过滤端口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值