原始套接字接收自己发送的消息
Raw sockets receiving messages sent by itself
我尝试使用原始套接字编写一些代码,同时我观察到一些奇怪的现象。考虑代码:
int rsfd = socket(AF_INET,SOCK_RAW,253);
if(rsfd<0)
{
perror("Raw socket not created");
}
else
{
struct sockaddr_in addr2;
memset(&addr2,0,sizeof(addr2));
addr2.sin_family = AF_INET;
addr2.sin_addr.s_addr = inet_addr("127.0.0.2");
/* if(connect(rsfd,(struct sockaddr*)&addr2,sizeof(addr2))<0)
{
perror("Could not connect");continue;
} */
}
现在,如果我删除注释部分,我通过此 rsfd 发送的任何消息也会被它自己接收。在另一端,我已经用 ip 地址 127.0.0.2
绑定了一个套接字。当我打印发送方套接字的 ip 地址时,它正在打印 127.0.0.1
但它仍然在接收用于 127.0.0.2
的数据包。当我添加评论部分中提到的连接请求时,这个问题就解决了。这看起来很奇怪,因为另一方面,没有人接受或监听这个地址,而且,我正在使用 sendto
和 recvfrom
函数来发送和接收用于无连接套接字的数据包。我的问题是,为什么会这样?这个连接请求是如何解决这里的问题的?
Now if I [don't connect()
the socket], whatever message I am sending through this rsfd is also being received by itself.
我首先注意到原始套接字是 POSIX 的扩展。 Linux 提供了它们,我认为其他系统也提供了它们,但是它们的行为细节在不同的实现中不一定是一致的。
话虽如此,问题似乎可能是您没有bind()
将您的套接字连接到任何地址。例如,在 Linux 上,the docs for raw sockets 请注意
A raw socket can be bound to a specific local address using the
bind(2)
call. If it isn't bound, all packets with the specified IP
protocol are received.
(强调已添加。)在原始套接字具有这种行为的系统上,如果您通过既未绑定也未连接的原始 IP 套接字将数据包发送到 IP 环回地址,那么是的,源套接字将接收他们,或者至少可能会。
目前还不清楚为什么连接套接字可以解决问题,或者为什么它甚至可以成功。 connect()
的行为对于标准套接字类型 SOCK_DGRAM
、SOCK_STREAM
和 SOCK_SEQPACKET
以外的套接字类型未指定。但是,您观察到的行为与 connect()
对原始套接字的影响一致,就像它对数据报套接字的影响一样,这些套接字也是无连接的:
If the socket sockfd
is of type SOCK_DGRAM
, then addr
is the address
to which datagrams are sent by default, and the only address from
which datagrams are received.
然而,我建议不要依赖于发现的行为,而是遵循记录在案的(至少在 Linux 上)将套接字绑定到地址(包括端口)的过程,然后与之通信地址。
我尝试使用原始套接字编写一些代码,同时我观察到一些奇怪的现象。考虑代码:
int rsfd = socket(AF_INET,SOCK_RAW,253);
if(rsfd<0)
{
perror("Raw socket not created");
}
else
{
struct sockaddr_in addr2;
memset(&addr2,0,sizeof(addr2));
addr2.sin_family = AF_INET;
addr2.sin_addr.s_addr = inet_addr("127.0.0.2");
/* if(connect(rsfd,(struct sockaddr*)&addr2,sizeof(addr2))<0)
{
perror("Could not connect");continue;
} */
}
现在,如果我删除注释部分,我通过此 rsfd 发送的任何消息也会被它自己接收。在另一端,我已经用 ip 地址 127.0.0.2
绑定了一个套接字。当我打印发送方套接字的 ip 地址时,它正在打印 127.0.0.1
但它仍然在接收用于 127.0.0.2
的数据包。当我添加评论部分中提到的连接请求时,这个问题就解决了。这看起来很奇怪,因为另一方面,没有人接受或监听这个地址,而且,我正在使用 sendto
和 recvfrom
函数来发送和接收用于无连接套接字的数据包。我的问题是,为什么会这样?这个连接请求是如何解决这里的问题的?
Now if I [don't
connect()
the socket], whatever message I am sending through this rsfd is also being received by itself.
我首先注意到原始套接字是 POSIX 的扩展。 Linux 提供了它们,我认为其他系统也提供了它们,但是它们的行为细节在不同的实现中不一定是一致的。
话虽如此,问题似乎可能是您没有bind()
将您的套接字连接到任何地址。例如,在 Linux 上,the docs for raw sockets 请注意
A raw socket can be bound to a specific local address using the
bind(2)
call. If it isn't bound, all packets with the specified IP protocol are received.
(强调已添加。)在原始套接字具有这种行为的系统上,如果您通过既未绑定也未连接的原始 IP 套接字将数据包发送到 IP 环回地址,那么是的,源套接字将接收他们,或者至少可能会。
目前还不清楚为什么连接套接字可以解决问题,或者为什么它甚至可以成功。 connect()
的行为对于标准套接字类型 SOCK_DGRAM
、SOCK_STREAM
和 SOCK_SEQPACKET
以外的套接字类型未指定。但是,您观察到的行为与 connect()
对原始套接字的影响一致,就像它对数据报套接字的影响一样,这些套接字也是无连接的:
If the socket
sockfd
is of typeSOCK_DGRAM
, thenaddr
is the address to which datagrams are sent by default, and the only address from which datagrams are received.
然而,我建议不要依赖于发现的行为,而是遵循记录在案的(至少在 Linux 上)将套接字绑定到地址(包括端口)的过程,然后与之通信地址。