首页 > 解决方案 > 接收自己发送的消息的原始套接字

问题描述

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

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

标签: csocketsnetworkingraw-sockets

解决方案


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

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

话虽如此,问题似乎很可能是您没有bind()将套接字连接到任何地址。例如,在 Linux 上,原始套接字的文档指出

bind(2)可以使用调用 将原始套接字绑定到特定的本地地址 。如果未绑定,则接收所有具有指定 IP 协议的数据包。

(强调了。)在原始套接字具有这种行为的系统上,如果您通过既未绑定也未连接的原始 IP 套接字将数据包发送到 IP 环回地址,那么是的,源套接字将接收它们,或者至少可能会。

目前还不清楚为什么连接套接字可以解决问题,或者为什么它甚至完全成功。对于标准类型、、 和connect()以外的套接字类型,未指定 的行为。但是,您观察到的行为与对原始套接字的影响是一致的,就像它对数据报套接字一样,它们也是无连接的:SOCK_DGRAMSOCK_STREAMSOCK_SEQPACKETconnect()

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

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


推荐阅读