сокет udp sendto неявное связывание - PullRequest
0 голосов
/ 30 января 2019

Я смотрю на пример клиента udp здесь: http://www.linuxhowtos.org/data/6/client_udp.c

фрагмент:

/* UDP client in the internet domain */
   struct sockaddr_in server, from;
   //...snipped

   sock= socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) error("socket");

   server.sin_family = AF_INET;
   hp = gethostbyname(argv[1]);
   if (hp==0) error("Unknown host");

   bcopy((char *)hp->h_addr, 
        (char *)&server.sin_addr,
         hp->h_length);
   server.sin_port = htons(atoi(argv[2]));
   length=sizeof(struct sockaddr_in);

   //... snipped       

   n=sendto(sock,buffer,
            strlen(buffer),0,(const struct sockaddr *)&server,length);
   if (n < 0) error("Sendto");
   n = recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length);
   if (n < 0) error("recvfrom");
   //... snipped    

Я пытаюсь понять, как он знает, откуда получить сообщение.Я знаю, когда sendto вызывается, выбирается доступный порт, который встроен в сообщение udp, и серверное приложение может прочитать его и ответить на него.Как клиентский код узнает, что получил сообщение на этот порт?

Этот ответ: https://stackoverflow.com/a/48245273/2748602 указывает на наличие неявного связывания при вызове функции sendto.Как это работает?Это на самом деле привязка со случайным номером доступного порта, который является постоянным, как если бы я звонил bind, или что-то еще?Кажется, есть какой-то аспект постоянства.Просто интересуюсь чуть более подробно.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Там - это неявное связывание, если сокет не связан, поскольку все пакеты должны нести оба порта-источника.Таким образом, API предполагает, что если вы не заботитесь о порте, чтобы заранее связать свой сокет, то он может просто связать сокет со случайным портом.И хотя, к сожалению, я не знаю подробностей реализации sendto, я могу предложить некоторую официальную документацию.

Для Linux со страницы руководства udp :

Когда создается сокет UDP, его локальный и удаленный адреса не указываются.Датаграммы могут быть отправлены немедленно, используя sendto (2) или sendmsg (2) с действительным адресом назначения в качестве аргумента.При вызове connect (2) для сокета устанавливается адрес назначения по умолчанию, и теперь дейтаграммы можно отправлять с использованием send (2) или write (2) без указания адреса назначения.По-прежнему можно отправлять сообщения другим адресатам, передавая адрес в sendto (2) или sendmsg (2). Для получения пакетов сокет может быть сначала привязан к локальному адресу с помощью bind (2).* В противном случае уровень сокетов автоматически назначит свободный локальный порт из диапазона, определенного в / proc / sys / net / ipv4 / ip_local_port_range, и свяжет сокет с INADDR_ANY .

Для Windowsфрагмент из документации для sendto * Winsock 2 :

Если сокет не связан, уникальные значения назначаются локальной ассоциацией системой, а сокетзатем помечается как связанный .Если сокет подключен, функция getsockname может использоваться для определения локального IP-адреса и порта, связанного с сокетом.

0 голосов
/ 30 января 2019

... существует неявное связывание при вызове функции sendto.Как это работает?Действительно ли это связывание со случайным номером доступного порта, которое является таким же постоянным, как если бы я позвонил, связывание или что-то еще?

man ip(7):

   ip_local_port_range (since Linux 2.2)
          This file contains two integers that define the default local
          port range allocated to sockets that are not explicitly bound
          to a port number—that is, the range used for ephemeral ports.
          An ephemeral port is allocated to a socket in the following
          circumstances:

          *  the port number in a socket address is specified as 0 when calling bind(2);

          *  listen(2) is called on a stream socket that was not previously bound;

          *  connect(2) was called on a socket that was not previously bound;

          *  sendto(2) is called on a datagram socket that was not previously bound.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...