На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие друзья! Поздравляем вас с днём Победы!
msm.ru
  
    > Приём UDP сообщений , под linux
      Доброго всем времени суток!

      Есть программа-клиент, отправляющая мне с удалённого компа UDP сообщения, и есть программа-сервер на моём компе, которая должна их ловить. Если верить снифферу, то пакеты успешно до меня доходят, отправителю тут же возвращают ICMP Destination unreachable (Host administratively prohibited), но программа-сервер ничего не получает.

      Когда я тестировал ту же программу на локальном хосте (и сервер и клиент), всё работало. В чём может быть дело? Может кто-то сталкивался или просто догадывается?

      Код программы-клиента:
      ExpandedWrap disabled
        #include <stdlib.h>
        #include <stdio.h>
        #include <errno.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string>
        #include "string.h"
         
        using namespace std;
         
        int main(int argc, char** argv) {
            int m_sock;                     // дескриптор сокета
            sockaddr_in m_addr;             // переменная адреса интерфейса
            sockaddr_in s_addr;             // переменная адреса получателя
            string my_addr = "192.168.0.211";// Адрес локального интерфейса
            string ip_addr = "192.168.0.90";// Адрес получателя
         
            /* Создание сокета и присвоение значения дескриптору сокета для UDP пакетов
             * PF_INET    - IP protocol family
             * SOCK_DGRAM - Raw protocol interface */
            if ((m_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                perror("socket");
                return -1;
            }
         
            /* Обнуляем переменную m_addr и забиваем её нужными значениями */
            bzero(&m_addr, sizeof(m_addr));
            m_addr.sin_family   = AF_INET;  // обязательно AF_INET!
            m_addr.sin_port     = htons(0); // 0 - выдать порт автоматом
            /* Переводим адрес в нужный нам формат */
            if (inet_aton(my_addr.c_str(), &m_addr.sin_addr) == 0) {
                perror("inet_aton");
                close(m_sock);
                return -1;
            }
         
            /* Биндим сокет */
            if (bind(m_sock, (struct sockaddr*)&m_addr, sizeof(m_addr)) < 0) {
                perror("bind");
                close(m_sock);
                return -1;
            }
         
            /* Обнуляем переменную s_addr и забиваем её нужными значениями */
            bzero(&s_addr, sizeof(s_addr));
            s_addr.sin_family   = AF_INET;
            s_addr.sin_port     = htons(1024);
            /* Переводим адрес в нужный нам формат */
            if (inet_aton(ip_addr.c_str(), &s_addr.sin_addr) == 0) {
                perror("inet_aton");
                close(m_sock);
                return -1;
            }
         
            /* Засыпаем адресата пачкой пакетов */
            char msg[1024] = "hey, hey baby! whoh-whah! i wanna kno-o-ow if you'll be my girl.";
            while(1) {
                if (sendto(m_sock, msg, 1024, MSG_NOSIGNAL, (struct sockaddr*)&s_addr, sizeof(s_addr)) < 0) {
                    perror("sendto");
                    close(m_sock);
                    return -1;
                }
                sleep(1);
            }
         
            /* Закрываем сокет и выходим из программы */
            close(m_sock);
            return (EXIT_SUCCESS);
        }


      Код программы-сервера:
      ExpandedWrap disabled
        #include <stdlib.h>
        #include <stdio.h>
        #include <errno.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string>
        #include "string.h"
         
        using namespace std;
         
        int main(int argc, char** argv) {
            int m_sock;                     // дескриптор сокета
            sockaddr_in m_addr;             // переменная адреса интерфейса
            string my_addr = "192.168.0.90";// Адрес локального интерфейса
         
            /* Создание сокета и присвоение значения дескриптору сокета для UDP пакетов
             * PF_INET    - IP protocol family
             * SOCK_DGRAM - Raw protocol interface */
            if ((m_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                perror("socket");
                return -1;
            }
         
            /* Обнуляем переменную m_addr и забиваем её нужными значениями */
            bzero(&m_addr, sizeof(m_addr));
            m_addr.sin_family   = AF_INET;  // обязательно AF_INET!
            m_addr.sin_port     = htons(1024); // 0 - выдать порт автоматом
            /* Переводим адрес в нужный нам формат */
            if (inet_aton(my_addr.c_str(), &m_addr.sin_addr) == 0) {
                perror("inet_aton");
                close(m_sock);
                return -1;
            }
         
            /* Биндим сокет */
            if (bind(m_sock, (struct sockaddr*)&m_addr, sizeof(m_addr)) < 0) {
                perror("bind");
                close(m_sock);
                return -1;
            }
         
            /* Получаем пакеты от отправителя */
            char recvline[1024];
            int bytesrecv;
            while(1) {
                if ((bytesrecv = recvfrom(m_sock, recvline, 1024, 0, (sockaddr*)NULL, NULL)) < 0) {
                    perror("recvfrom");
                    close(m_sock);
                    return -1;
                }
                printf("Message received! Size: %d\n", bytesrecv);
            }
         
            /* Закрываем сокет и выходим из программы */
            close(m_sock);
            return (EXIT_SUCCESS);
        }


      Ни единого recvfrom не произошло, хотя пришла уже не одна тысяча пакетов.

      Кусок лога WireShark, который повторяется каждую секунду:
      Цитата
      192.168.0.211 192.168.0.90 UDP Source port: 35160 Destination port: 1024
      192.168.0.90 192.168.0.211 ICMP Destination unreachable (Host administratively prohibited)


      PS:
      192.168.0.90 - ip моего компа
      192.168.0.211 - ip удалённой тачки
      Обмен данными производится через 1024 порт.

      PPS:
      Поначалу грешил на порт, пробовал менять его на меньший и больший - ничего не меняется.

      PPPS:
      Грешил на адрес интерфейса, пробовал делать my_addr.sin_addr.s_addr = htonl(INADDR_ANY) - тоже никакого эффекта.
        Цитата gabbear @
        ICMP Destination unreachable (Host administratively prohibited)
        Firewall



        Цитата gabbear @
        ExpandedWrap disabled
          /* Биндим сокет */
        Для клиента это лишнее.



        Цитата gabbear @
        Поначалу грешил на порт, пробовал менять его на меньший и больший - ничего не меняется.
        Должно менятся. Или ты сидишь по root'ом? :o
          Цитата albom @
          Цитата gabbear @
          ICMP Destination unreachable (Host administratively prohibited)
          Firewall

          Хм. А почему тогда сниффер эти пакеты ловит?

          Цитата albom @
          Цитата gabbear @
          Поначалу грешил на порт, пробовал менять его на меньший и больший - ничего не меняется.
          Должно менятся. Или ты сидишь по root'ом? :o

          Пробовал и под рутом и без него - точно так же пакеты идут, сниффер их ловит, ICMP ответ уходит, сервер ничего не видит.
            Это к тому, что не root'у нельзя биндить порт с номером меньше 1024. Изменение должно быть в виде ошибки в сервере при вызове bind().

            Цитата gabbear @
            А почему тогда сниффер эти пакеты ловит?
            Потому что переводит карту в promiscuous режим и слушает весь сетевой поток, а не работает на уровне пакетов как firewall.
              Цитата albom @
              Это к тому, что не root'у нельзя биндить порт с номером меньше 1024. Изменение должно быть в виде ошибки в сервере при вызове bind().

              Цитата gabbear @
              А почему тогда сниффер эти пакеты ловит?
              Потому что переводит карту в promiscuous режим и слушает весь сетевой поток, а не работает на уровне пакетов как firewall.

              Спасибо большое. Вчера тряс нашего админа на тему всяческих фаерволов и сетевых фильтров - убеждал, что нигде ничего. Но почему-то оказался включён фаервол. Заработало.
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0298 ]   [ 16 queries used ]   [ Generated: 10.05.24, 17:42 GMT ]