当前位置: 技术问答>linux和unix
请问一般套接字的绑定和原始套接字的绑定有什么区别吗
来源: 互联网 发布时间:2016-03-21
本文导语: 谢谢指点 | 对于SOCK_RAW的bind, man packet By default all packets of the specified protocol type are passed to a packet socket. To only get packets from a specific interface use bind...
谢谢指点
|
对于SOCK_RAW的bind, man packet
By default all packets of the specified protocol type are passed to a
packet socket. To only get packets from a specific interface use bind(2)
specifying an address in a struct sockaddr_ll to bind the packet socket
to an interface. Only the sll_protocol and the sll_ifindex address fields
are used for purposes of binding.
struct sockaddr_ll {
unsigned short sll_family; /* Always AF_PACKET */
unsigned short sll_protocol; /* Physical layer protocol */
int sll_ifindex; /* Interface number */
unsigned short sll_hatype; /* Header type */
unsigned char sll_pkttype; /* Packet type */
unsigned char sll_halen; /* Length of address */
unsigned char sll_addr[8]; /* Physical layer address */
};
By default all packets of the specified protocol type are passed to a
packet socket. To only get packets from a specific interface use bind(2)
specifying an address in a struct sockaddr_ll to bind the packet socket
to an interface. Only the sll_protocol and the sll_ifindex address fields
are used for purposes of binding.
struct sockaddr_ll {
unsigned short sll_family; /* Always AF_PACKET */
unsigned short sll_protocol; /* Physical layer protocol */
int sll_ifindex; /* Interface number */
unsigned short sll_hatype; /* Header type */
unsigned char sll_pkttype; /* Packet type */
unsigned char sll_halen; /* Length of address */
unsigned char sll_addr[8]; /* Physical layer address */
};
|
你可以研究一下内核的源码:
net/ipv4/raw.c
net/ipv4/af_inet.c
可以看出二者的bind函数有相当大的区别,实际上原始套接字的bind几乎什么正事也不做,这可以从其注释看出:
/* This gets rid of all the nasties in af_inet. -DaveM */
static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
int ret = -EINVAL;
int chk_addr_ret;
if (sk->sk_state != TCP_CLOSE || addr_len sk_net, addr->sin_addr.s_addr);
ret = -EADDRNOTAVAIL;
if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
goto out;
inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->saddr = 0; /* Use device */
sk_dst_reset(sk);
ret = 0;
out: return ret;
}
不过网上搜到的资料说:
调用bind函数后,发送数据包的源IP地址将是bind函数指定的地址。如是不调用bind,则内核将以发接口的主IP地址填充。如果设置了IP_HDRINCL,那么必须手工填充每个发送数据包的源IP地址。
可是从raw socket的bind函数来看,看不出这点,有知道的不妨讨论一下。
|
路过,等x86大哥
|
学习
|
也许是这句话设置了地址:
inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
|
又看了一下af_inet.c,发现主要的区别在于这几行:
inet->sport = htons(inet->num);
inet->daddr = 0;
inet->dport = 0;
换句话说,普通的socket的bind会设置端口,而raw socket不会
至于设置地址(之前指出的那行),则是都会有的
inet->sport = htons(inet->num);
inet->daddr = 0;
inet->dport = 0;
换句话说,普通的socket的bind会设置端口,而raw socket不会
至于设置地址(之前指出的那行),则是都会有的