BOOST UDP问题

时间:2018-10-27 21:31:24

标签: visual-c++ boost visual-studio-2017 udp

我正在编写将BOOST库用于UDP协议的程序。我仅在Windows上发生过错误,在CentOS 6.9(Linux)GCC上可以正常工作。

问题是 -当我使用send_to函数在特定IP或端口的套接字上写入数据并且假定IP / PORT无法正常工作时,则并行读取套接字通知我们认为它具有可供读取的数据。当我读取该数据时,使用本地套接字的长度为-1。

示例 :假设此UDP的服务器端口为9000,客户端端口为6000,客户端端口不起作用,并强制发送数据报包(UDP包) )从9000(服务器)到6000(客户端)。在这里,在读取套接字上,我们有数据及其 length = -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 :(得分:0)

如果将UDP数据包发送到没有套接字来处理该数据包的目标,则(通常)ICMP无法到达消息将发送到原始源IP。如果在那里收到,它将在发送方套接字上设置一个标志,以便在下一个套接字操作将问题传递给应用程序时,即下一个发送或接收将失败。

在实践中,目标可能不会发送无法到达的ICMP(禁用或速率受限),或者目标上,目的地或两者之间的某个位置的防火墙可能会阻止无法传递ICMP-阻止ICMP实际上并不罕见一般来说。在这种情况下,发件人将不会收到ICMP不可达消息,也无法将错误传播到应用程序。

因此,您的情况的不同之处可能是,在某些情况下,ICMP无法访问在到达原始发件人之前被阻止,而在其他情况下则没有。

有关更多信息,请参见boost::asio error for UDP async_receiveUDP socket fail to receive ECONNREFUSED