BOOST UDP проблема - PullRequest
       19

BOOST UDP проблема

0 голосов
/ 28 октября 2018

Я пишу программу для использования библиотеки BOOST для протокола UDP. Я столкнулся с ошибкой только в Windows, она работает правильно на CentOS 6.9 (Linux) GCC.

Проблема: - Когда я использую функцию send_to для записи данных в сокет для определенного IP-адреса или порта и предполагаю, что IP / PORT не работает, сокет параллельного чтения сообщает нам, что у него есть данные, доступные для чтения. Когда я читаю эти данные, они имеют длину = -1 с использованием собственного сокета.

Пример : предположим, что для этого UDP порт сервера равен 9000, а порт клиента 6000, порт клиента не работает, и принудительно отправляет пакеты дейтаграмм (пакеты UDP) с 9000 (сервер) до 6000 (клиент). Здесь на сокете чтения у нас есть данные и их длина = -1

Здесь, вопрос: почему сокет 9000 (сервер) имеет данные для чтения сразу после записи в сокет, но во время чтения он имеет длину -1.

Итак, если у кого-то есть решение этой проблемы, тогда, пожалуйста, обсудите.

Ниже приведен пример кода:

#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPCRECATED

#include "WinSock2.h"

#include <boost/asio.hpp>
using boost::asio::ip::udp;

boost::asio::io_service m_ioService;

bool DoesSocketHaveAnyData(udp::socket *m_lpSocket)
{

    // set the timeout to UDP_MILLISEC_WAIT_FOR_DATA seconds
    struct timeval tv;
    tv.tv_sec = 0;
    //tv.tv_usec = 1000 * 1000 * 20;    // UDP_MILLISEC_WAIT_FOR_DATA;
    tv.tv_usec = 1;                     // UDP_MILLISEC_WAIT_FOR_DATA;

    // We'll need to get the underlying native socket for this select call, in order to add a simple timeout on the read:
    int nativeSocket = (int)m_lpSocket->native_handle();

    fd_set fileDescriptorSet;
    FD_ZERO(&fileDescriptorSet);
    FD_SET(nativeSocket, &fileDescriptorSet);

    bool m_blnCheck = false;

    //Wait for message until timeout expires
    if (select(nativeSocket + 1, &fileDescriptorSet, NULL, NULL, &tv) == 0)
    {
        m_blnCheck = false;
    }
    else
    {
        if (!FD_ISSET(nativeSocket, &fileDescriptorSet)) 
        {
            m_blnCheck = false;
        }
        else
        {
            //Issue arise here -> Receice data here, upon checking length -1 (initially, sending data buffer to specific remote endpoint).


            //==> Way 1
            /*//boost::system::error_code ee;
            //size_t tt = m_lpSocket->available(ee);
            size_t m_availableNoOfBytes = m_lpSocket->available();
            if (m_availableNoOfBytes >= 2) { m_blnCheck = true; }*/

            //==> Way 2
            struct sockaddr_in src_addr;    /* Used to receive (addr,port) of sender */
            int src_addr_len;               /* Length of src_addr */
            int len;                        /* Length of result from nativeSocket */
            char line[BUFSIZ * 2] = { 0 };

            src_addr_len = sizeof(src_addr);

            len = recvfrom(nativeSocket, line, BUFSIZ * 2, MSG_PEEK /* flags */, (struct sockaddr *) &src_addr, &src_addr_len);
            /*printf("Msg from (%u,%u): `%s' (%u bytes)\n", src_addr.sin_addr.s_addr, src_addr.sin_port, line, len);*/

            if (len > 0)
            {
                m_blnCheck = true;
            }
            else
            {
                len = recvfrom(nativeSocket, line, BUFSIZ * 2, 0 /* flags */, (struct sockaddr *) &src_addr, &src_addr_len);
            }
        }
    }

    return m_blnCheck;
}


int main()
{
    int m_uiMyPortNumber = 9000;

    try {
        //boost::asio::ip::udp::endpoint boostEndPoint(boost::asio::ip::udp::v4(), m_uiMyPortNumber);
        udp::endpoint boostEndPoint(boost::asio::ip::address::from_string("192.168.1.117"), m_uiMyPortNumber);
        udp::socket *m_lpSocket = new udp::socket(m_ioService, boostEndPoint);


        bool blnCheck = false;
        do {

            m_lpSocket->set_option(boost::asio::socket_base::reuse_address(true));
            m_lpSocket->set_option(boost::asio::socket_base::broadcast(true));
            m_lpSocket->set_option(boost::asio::socket_base::do_not_route(true));

            boost::system::error_code error_obj;
            boost::asio::ip::udp::endpoint remote_endpoint(boost::asio::ip::address::from_string("192.168.1.121"), 6000);


            /////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //Issue arise here -> Sending data buffer to specific remote endpoint. Also, "remote endpoint" is not having opened UDP port.

            //=> Way 1: using boost 
            size_t  m_sendto = m_lpSocket->send_to(boost::asio::buffer((char *)"TEST", 4), remote_endpoint, 0, error_obj);
            if (error_obj) { return false; }


            //=> Way 2: using native socket
            /*struct sockaddr_in si_other;

            si_other.sin_family = AF_INET;
            si_other.sin_port = htons(6000);            

            #ifdef _WIN32_WINNT 0x0501
                        si_other.sin_addr.s_addr = inet_addr("192.168.1.121"); //for XP
            #else
                        inet_pton(AF_INET, "192.168.1.121", &inaddr.sin_addr.s_addr); //for Vista or higher
            #endif

            size_t m_sendto = sendto(m_lpSocket->native_handle(), (char *)"TEST", 4, 0, (struct sockaddr*) &si_other, sizeof(si_other));*/

            blnCheck = DoesSocketHaveAnyData(m_lpSocket);

        } while (blnCheck == false);

        printf("success\n");

    }
    catch (boost::system::system_error const &e) 
    {
        printf("%s\n", e.what());
    }

    getchar();
    return 0;
}

1 Ответ

0 голосов
/ 28 октября 2018

Если UDP-пакет отправляется получателю, у которого нет сокета для обработки этого пакета, то (обычно) сообщение с недоступным ICMP будет отправлено на исходный IP-адрес источника.Если он получен там, он установит флаг на сокете отправителя, так что проблема будет доставлена ​​приложению со следующей операцией сокета, то есть при следующей отправке или возврате произойдет сбой.

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

Таким образом, в вашем случае, вероятно, разница в том, что в некоторых случаях недоступность ICMP блокируется до того, как он достигнет исходного отправителяа в других случаях нет.

Для получения дополнительной информации см. Также ошибка boost :: asio для UDP async_receive и сокету UDP не удается получить ECONNREFUSED .

...