当我观察到一些奇怪的现象时,我试图用原始套接字编写一些代码。考虑代码:
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
函数发送和接收用于减少连接数的套接字的数据包。我的问题是,为什么会这样?此连接请求如何解决这里的问题?
答案 0 :(得分:1)
现在,如果我[不
connect()
套接字],则我自己通过此rsfd发送的任何消息也将被自己接收。
我首先注意到原始套接字是POSIX的扩展。 Linux提供了它们,我认为其他系统也可以提供它们,但是它们的行为细节并不确定在各个实现中是一致的。
话虽如此,问题似乎可能在于您没有bind()
将套接字插入任何地址。例如,在Linux上,the docs for raw sockets请注意
原始套接字可以使用以下方式绑定到特定的本地地址:
bind(2)
个电话。 如果未绑定,则所有具有指定IP的数据包 协议已收到。
(添加了强调。)在原始套接字具有该行为的系统上,如果您通过未绑定或未连接的原始IP套接字将数据包发送到IP回送地址,则是,源套接字将接收到它们,或至少可以做到。
目前尚不清楚为什么连接插座可以解决问题,或者为什么甚至不能成功。对于标准类型connect()
,SOCK_DGRAM
和SOCK_STREAM
以外的套接字类型,未指定SOCK_SEQPACKET
的行为。但是,您观察到的行为与connect()
一样对原始套接字有影响,就像它对数据报套接字一样,后者也是无连接的:
如果套接字
sockfd
的类型为SOCK_DGRAM
,则addr
是地址 默认情况下向哪个数据报发送,以及唯一的地址 接收到哪些数据报。
但是,我建议不要遵循已发现的行为,而应遵循已记录的过程(至少在Linux上是这样),将套接字绑定到地址(包括端口),并在该地址与之通信。