【发布时间】:2016-07-09 03:48:03
【问题描述】:
我正在尝试配置我的 MOCAP 节点(虚拟机)IP 地址以匹配我 PC 上 MOTIVE 软件的 IP 地址。 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.log]。 日志文件:/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 地址时会收到此错误?
【问题讨论】:
-
旁注:您可以避免使用
中定义的 strerror 进行此开关(errno){ ... }