Необработанные сокеты, принимающие сообщения, отправленные самим собой - PullRequest
0 голосов
/ 04 апреля 2019

Я пытался написать несколько кодов, используя необработанные сокеты, в то время как я наблюдал какое-то странное явление.Рассмотрим код:

                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 для отправки и получения пакетов, которые используются для сокетов без подключения.Мой вопрос, , почему это происходит?Как этот запрос на соединение решает проблему здесь?

1 Ответ

1 голос
/ 04 апреля 2019

Теперь, если я [не connect() сокет], любое сообщение, которое я посылаю через этот rsfd, также будет получено само по себе.

Сначала отметим, что необработанные сокеты являются расширением POSIX.Linux предлагает их, и я думаю, что другие системы делают то же самое, но детали их поведения не обязательно будут одинаковыми для всех реализаций.

С учетом сказанного, проблема, вероятно, заключается в том, что вы не bind() ingВаш сокет на любой адрес.Например, в Linux в документах для необработанных сокетов обратите внимание, что

Необработанный сокет может быть связан с конкретным локальным адресом с помощью вызова bind(2). Если он не связан, все пакеты с указанным IP-протоколом принимаются.

(выделение добавлено.) В системе, где необработанные сокеты имеют такое поведение, если вы 'повторная отправка пакетов на IP-адрес обратной связи через необработанный IP-сокет, который не связан и не подключен, тогда да, исходный сокет получит их или, по крайней мере, может это сделать.

Неясно, почему подключение сокета решает проблемуили почему это вообще успешно.Поведение connect() не определено для типов сокетов, отличных от стандартных, SOCK_DGRAM, SOCK_STREAM и SOCK_SEQPACKET.Однако наблюдаемое вами поведение согласуется с тем, что connect() оказывает влияние на необработанные сокеты, как это влияет на сокеты дейтаграмм, которые также не имеют соединения:

Если сокет sockfd имеет тип SOCK_DGRAM, тогда addr - это адрес, по которому дейтаграммы отправляются по умолчанию, и единственный адрес, с которого принимаются дейтаграммы.

Вместо того, чтобы полагаться на это обнаруженное поведениетем не менее, я предлагаю следовать документированной (по крайней мере в Linux) процедуре привязки сокета к адресу (включая порт) и связи с ним по этому адресу.

...