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

时间:2019-04-04 13:54:30

标签: c sockets networking raw-sockets

当我观察到一些奇怪的现象时,我试图用原始套接字编写一些代码。考虑代码:

                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函数发送和接收用于减少连接数的套接字的数据包。我的问题是,为什么会这样?此连接请求如何解决这里的问题?

1 个答案:

答案 0 :(得分:1)

  

现在,如果我[不connect()套接字],则我自己通过此rsfd发送的任何消息也将被自己接收。

我首先注意到原始套接字是POSIX的扩展。 Linux提供了它们,我认为其他系统也可以提供它们,但是它们的行为细节并不确定在各个实现中是一致的。

话虽如此,问题似乎可能在于您没有bind()将套接字插入任何地址。例如,在Linux上,the docs for raw sockets请注意

  

原始套接字可以使用以下方式绑定到特定的本地地址:          bind(2)个电话。 如果未绑定,则所有具有指定IP的数据包          协议已收到。

(添加了强调。)在原始套接字具有该行为的系统上,如果您通过未绑定或未连接的原始IP套接字将数据包发送到IP回送地址,则是,源套接字将接收到它们,或至少可以做到。

目前尚不清楚为什么连接插座可以解决问题,或者为什么甚至不能成功。对于标准类型connect()SOCK_DGRAMSOCK_STREAM以外的套接字类型,未指定SOCK_SEQPACKET的行为。但是,您观察到的行为与connect()一样对原始套接字有影响,就像它对数据报套接字一样,后者也是无连接的:

  

如果套接字sockfd的类型为SOCK_DGRAM,则addr是地址          默认情况下向哪个数据报发送,以及唯一的地址          接收到哪些数据报。

但是,我建议不要遵循已发现的行为,而应遵循已记录的过程(至少在Linux上是这样),将套接字绑定到地址(包括端口),并在该地址与之通信。