原始套接字接收自己发送的消息

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 的数据包。当我添加评论部分中提到的连接请求时,这个问题就解决了。这看起来很奇怪,因为另一方面,没有人接受或监听这个地址,而且,我正在使用 sendtorecvfrom 函数来发送和接收用于无连接套接字的数据包。我的问题是,为什么会这样?这个连接请求是如何解决这里的问题的?

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_DGRAMSOCK_STREAMSOCK_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 上)将套接字绑定到地址(包括端口)的过程,然后与之通信地址。