(C ++)初始化MOCAP节点时出现EINVAL错误

时间:2016-07-08 19:35:11

标签: c++ ros

我正在尝试配置我的MOCAP节点(虚拟机)IP地址以匹配我的PC上的MOTIVE软件。 MOCAP.yaml文件最初设置为224.0.0.1,但每次我更改它以匹配我的机器的IP地址时,它会导致EINVAL错误,如下所示:

在抛出' SocketException'

的实例后终止调用

what():设置套接字选项失败:EINVAL

=============================================== ==========================

必需的进程[mocap_node-1]已经死亡! 进程已经死亡[pid 4575,退出代码-6,cmd / home / radlab / mocap / devel / lib / mocap_optitrack / mocap_node __name:= mocap_node __log:= / home / radlab / .ros / log / 3fe16008-4521-11e6- 9638-080027e2597b / mocap_node-1.登录]。 日志文件:/home/radlab/.ros/log/3fe16008-4521-11e6-9638-080027e2597b/mocap_node-1*.log

开始关机!

=============================================== ==========================

这是socket.cpp的代码

 /*
 * Socket.cpp
 *
 *  Created on: 14.11.2008
 *      Author:
 */

 // Implementation of the Socket class.

#include "mocap_optitrack/socket.h"
#include <cstring>
#include <cerrno>
#include <fcntl.h>
#include <iostream>
#include <stdio.h>
#include <sstream>

#include <ros/ros.h>

UdpMulticastSocket::UdpMulticastSocket( const int local_port, const std::string multicast_ip ) 
{
  // Create a UDP socket
  ROS_INFO( "Creating socket..." );
  m_socket = socket( AF_INET, SOCK_DGRAM, 0 );
  if( m_socket < 0 )
    throw SocketException( strerror( errno ) );

  // Allow reuse of local addresses
  ROS_INFO( "Setting socket options..." );
  int option_value = 1;
  int result = setsockopt( m_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value, sizeof( int ) );
  if( result == -1 )
  {
    std::stringstream error;
    error << "Failed to set socket option: ";
    switch( errno )
    {
      case EBADF:
  error << "EBADF";
  break;
      case EFAULT:
  error << "EFAULT";
  break;
      case EINVAL:
  error << "EINVAL";
  break;
      case ENOPROTOOPT:
  error << "ENOPROTOOPT";
  break;
      case ENOTSOCK:
  error << "ENOTSOCK";
  break;
      default:
  error << "unknown error";
  break;
    }
    throw SocketException( error.str().c_str() );    
  }

  // Fill struct for local address
  memset ( &m_local_addr, 0, sizeof ( m_local_addr ) );
  m_local_addr.sin_family = AF_INET;
  m_local_addr.sin_addr.s_addr = htonl( INADDR_ANY );
  m_local_addr.sin_port = htons( local_port );
  ROS_INFO( "Local address: %s:%i", inet_ntoa( m_local_addr.sin_addr ), ntohs( m_local_addr.sin_port ) );

  // Bind the socket
  ROS_INFO( "Binding socket to local address..." );
  result = bind( m_socket, (sockaddr*)&m_local_addr, sizeof( m_local_addr ));
  if( result == -1 )
  {
    std::stringstream error;
    error << "Failed to bind socket to local address:" << strerror( errno );
    throw SocketException( error.str().c_str() );
  }

  // Join multicast group
  struct ip_mreq mreq;
  mreq.imr_multiaddr.s_addr = inet_addr( multicast_ip.c_str() );
  mreq.imr_interface = m_local_addr.sin_addr;
  ROS_INFO( "Joining multicast group %s...", inet_ntoa( mreq.imr_multiaddr ) );

  result = setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
  if( result == -1 )
  {
    std::stringstream error;
    error << "Failed to set socket option: ";
    switch( errno )
    {
      case EBADF:
  error << "EBADF";
  break;
      case EFAULT:
  error << "EFAULT";
  break;
      case EINVAL:
  error << "EINVAL";
  break;
      case ENOPROTOOPT:
  error << "ENOPROTOOPT";
  break;
      case ENOTSOCK:
  error << "ENOTSOCK";
  break;
      default:
  error << "unknown error";
  break;
    }
     throw SocketException( error.str().c_str() );    
  }

  // Make socket non-blocking
  ROS_INFO( "Enabling non-blocking I/O" );
  int flags = fcntl( m_socket, F_GETFL , 0 );
  result = fcntl(m_socket, F_SETFL, flags | O_NONBLOCK);
  if( result == -1 )
  {
    std::stringstream error;
    error << "Failed to enable non-blocking I/O: " << strerror( errno );
    throw SocketException( error.str().c_str() );
  }
}

UdpMulticastSocket::~UdpMulticastSocket()
{
  close( m_socket );
}

int UdpMulticastSocket::recv()
{
  memset ( buf, 0, MAXRECV + 1 );

  sockaddr_in remote_addr;
  int addr_len = sizeof(struct sockaddr);
  int status = recvfrom(
    m_socket,
    buf,
    MAXRECV,
    0,
    (sockaddr *)&remote_addr,
    (socklen_t*)&addr_len);

  if( status > 0 )
    ROS_DEBUG( "%4i bytes received from %s:%i", status, inet_ntoa( remote_addr.sin_addr ), ntohs( remote_addr.sin_port ) );
  else if( status == 0 )
    ROS_INFO( "Connection closed by peer" );

  return status;
}

任何人都可以帮我弄清楚当我更改IP地址时出现此错误的原因吗?

1 个答案:

答案 0 :(得分:0)

我不知道mocap或者是什么动机,但我认为你正在尝试使用非多播ip-address加入第79行的多播组。这可能是通过std ::传递给函数的内容来自.yaml文件的字符串multicast_ip。

参见手册页:

   IP_ADD_MEMBERSHIP (since Linux 1.2)
          Join a multicast group.  Argument is an ip_mreqn structure.

              struct ip_mreqn {
                  struct in_addr imr_multiaddr; /* IP multicast group
                                                   address */
                  struct in_addr imr_address;   /* IP address of local
                                                   interface */
                  int            imr_ifindex;   /* interface index */
              };

          imr_multiaddr contains the address of the multicast group the
          application wants to join or leave.  It must be a valid
          multicast address (or setsockopt(2) fails with the error
          EINVAL).  imr_address is the address of the local interface
          with which the system should join the multicast group; if it
          is equal to INADDR_ANY, an appropriate interface is chosen by
          the system.  imr_ifindex is the interface index of the
          interface that should join/leave the imr_multiaddr group, or 0
          to indicate any interface.

          The ip_mreqn structure is available only since Linux 2.2.  For
          compatibility, the old ip_mreq structure (present since Linux
          1.2) is still supported; it differs from ip_mreqn only by not
          including the imr_ifindex field.  (The kernel determines which
          structure is being passed based on the size passed in optlen.)

          IP_ADD_MEMBERSHIP is valid only for setsockopt(2).