recvfrom() разблокирует при получении пакета udp, но возвращает 0 как размер прочитанных байтов (используя oscpack)

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

Я наткнулся на оспак, который использует udp реализовать передачу сообщений для открытого управления звуком. Я скомпилировал его в Linux с gcc4.7.1 как общий объект, используя make lib, Обратите внимание, что я должен добавить опцию -fPIC в COPTS переменная в Makefile,

Имея общую библиотеку, я написал небольшое приложение для проверки концепции, в котором для прослушивания сообщений используется отдельный поток, а в основном потоке он ожидает какую-то строку из stdin переслать его в другое приложение. Я выполняю 2 очень похожие экземпляры этого приложения. Просто во втором случае я поменял местами PORT_RCV а также PORT_SND номера.


Актуальная проблема начинается здесь:

Проблема, с которой я сталкиваюсь, заключается в том, что на приемном конце, когда вызов osc::UdpSocket::ReceiveFrom() (который в конечном итоге запускает recvfrom()) разблокирует, я получаю возвращаемое значение прочитанных байтов, равное нулю (0). Так же char * data указатель по-прежнему указывает на ноль. По сути, я не получил строку из приложения отправителя, хотя функция recvfrom () разблокирована в нужное время.

Из страниц справочника я прочитал, что recv и recvfrom могут возвращать значение 0, когда отправитель закрыл соединение. Но отправитель в этом случае использует udp, т.е. соединение без соединения...:), поэтому я не уверен, применимо ли это здесь.

Я пытался использовать netcat прослушивать сообщения udp в соответствующем порту и проверять, что хотя бы часть отправителя работает. Действительно с netcat -u -l -p <sender port of the running instance> Я получаю сообщения, которые я печатаю. Так что, вероятно, проблема связана с получателем.

Вопрос: правильно ли я использую recvfrom?


пожалуйста, прикрепите код к тестовому приложению межпроцессного взаимодействия (на самом деле это дуплексный мессенджер). Чтобы выполнить 2 из них, сначала загрузите и скомпилируйте как библиотеку oscpack библиотека. Затем скопируйте приведенный ниже источник в два файла и поменяйте местами PORT_RCV а также PORT_SND цифры на 2-й исходный файл.

Затем скомпилируйте каждый с:

#compile
g++ -g -Wall -Wextra -pedantic -std=c++11  -I../oscpack -c -o "obj_dbg/messenger.opp" "src/messenger.cpp"

#link
g++ -g -Wall -Wextra -pedantic -std=c++11  -I../oscpack  obj_dbg/messenger.opp -o "messenger_dbg" -L../oscpack -pthread -loscpack

Затем выполните их и введите слово, нажмите ввод и ожидайте (не) увидеть его в другом приложении.

#include <iostream>
#include <string>
#include <string.h>

#include <thread>

#include <unistd.h>

#include "osc/OscReceivedElements.h"
#include "osc/OscPacketListener.h"
#include "ip/UdpSocket.h"

#include "osc/OscOutboundPacketStream.h"
#include "ip/UdpSocket.h"

using namespace std;
using namespace osc;

#define ADDRESS "127.0.0.1"
#define PORT_RCV 34343U
#define PORT_SND 34344U

#define IP_MTU_SIZE 1536

class EnaluPacketListener : public OscPacketListener
{
    protected:
        void ProcessMessage( const ReceivedMessage& m, const IpEndpointName& /*remoteEndpoint*/ )
        {
            //ReceivedMessageArgumentStream args = m.ArgumentStream();
            ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
            try{
                if( strcmp( m.AddressPattern(), "/info" ) == 0 )
                {
                    msg.clear();
                    msg = (arg++)->AsString();
                    //args >> msg >> EndMessage;
                    if( arg != m.ArgumentsEnd() )
                        std::cout << "more args exist\n";
                }
            }
            catch( Exception& e )
            {
                // any parsing errors such as unexpected argument types, or
                // missing arguments get thrown as exceptions.
                std::cout << "error while parsing message: "
                << m.AddressPattern() << ": " << e.what() << "\n";
            }
        }
    public:
        std::string msg;
};



void sendMsg(UdpTransmitSocket & transmitSocket , std::string const & msgTitle , std::string const & msg)
{
    char buffer[IP_MTU_SIZE];
    osc::OutboundPacketStream p( buffer, IP_MTU_SIZE );

    p.Clear();
    //p << osc::BeginBundleImmediate;
    p << osc::BeginMessage( msgTitle.c_str() );
    p << msg.c_str();
    p << osc::EndMessage;
    //p << osc::EndBundle;

    transmitSocket.Send( p.Data(), p.Size() );
}


void rcvThread(bool bExit)
{
    IpEndpointName ipen(ADDRESS,PORT_RCV);
    UdpReceiveSocket s(ipen);
    EnaluPacketListener pckParser;
    IpEndpointName ipenRcv;
    char * buffer = nullptr;
    int bufferSize = 0U;
    while (!bExit)
    {
        std::cout << "hello1\n";
        int i = s.ReceiveFrom(ipenRcv,buffer,bufferSize);
        if (i > 0)
        {
            std::cout << "bufferSize=" << bufferSize << " , buffer: " << buffer << std::endl;
            //we have data
            pckParser.ProcessPacket(buffer,bufferSize,ipenRcv);
            std::cout << "rcved: "  << pckParser.msg << "\n";
        }
        sleep(1);
    }
}

//int main(int argc, char* argv[])
int main(int , char**)
{
    bool bExit = false;
    UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, PORT_SND ) );

    std::thread thr(rcvThread, std::ref(bExit));

    std::string str;
    while (!bExit)
    {
        std::cin >> str;
        if ((!str.empty()) && (str.compare("q") != 0))
            sendMsg(transmitSocket,"info",str);
        else
            bExit = true;
    }

    thr.join();

    return 0;
}

1 ответ

Решение
char * buffer = nullptr;
int bufferSize = 0U;

Проблемы здесь.

    int i = s.ReceiveFrom(ipenRcv,buffer,bufferSize);

Вы говорите ReceiveFrom() получить в буфер нулевой длины, на который указывает нулевой указатель, так он и возвращает ноль. Что еще это может сделать? Изменить на:

char buffer[4096]; // or whatever you need
// ...
int i = s.ReceiveFrom(ipenRcv,buffer,sizeof buffer);
Другие вопросы по тегам