socket_node.cpp
Go to the documentation of this file.
1 
26 #include "ros/ros.h"
27 #include "nmea_msgs/Sentence.h"
28 
29 #include "nmea_comms/rx.h"
30 #include "nmea_comms/tx.h"
31 
32 #include <poll.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 
36 
37 void msg_callback(const nmea_msgs::SentenceConstPtr sentence_msg_ptr)
38 {
39  // noop
40 }
41 
42 
43 int main(int argc, char **argv)
44 {
45  ros::init(argc, argv, "nmea_socket_node");
46  ros::NodeHandle n_local("~");
48 
49  int listener_fd = socket(AF_INET, SOCK_STREAM, 0);
50  if (listener_fd < 0)
51  {
52  ROS_FATAL("ERROR opening socket");
53  ros::shutdown();
54  }
55 
56  int port;
57  n_local.param("port", port, 29500);
58 
59  std::string frame_id;
60  n_local.param<std::string>("frame_id", frame_id, "navsat");
61 
62  /* Initialize socket structure */
63  struct sockaddr_in serv_addr, cli_addr;
64  bzero((char *) &serv_addr, sizeof(serv_addr));
65  serv_addr.sin_family = AF_INET;
66  serv_addr.sin_addr.s_addr = INADDR_ANY;
67  serv_addr.sin_port = htons(port);
68 
69  /* Now bind the host address using bind() call.*/
70  int previous_success = 1;
71  while (1)
72  {
73  if (bind(listener_fd, (struct sockaddr *) &serv_addr,
74  sizeof(serv_addr)) < 0)
75  {
76  if (previous_success)
77  {
78  ROS_ERROR("Unable to bind socket. Is port %d in use? Retrying every 1s.", port);
79  previous_success = 0;
80  }
81  ros::Duration(1.0).sleep();
82  }
83  else
84  {
85  break;
86  }
87  }
88 
89  // Start ROS spinning in the background.
90  ros::AsyncSpinner spinner(1);
91  spinner.start();
92 
93  // Dummy publisher and subscriber.
94  // These are here because rospy has some bugs related to setting up
95  // and tearing down the same connection repeatly. So having these topics
96  // persistently available avoids issues with external Python-based nodes.
97  // See: https://github.com/ros/ros_comm/issues/129
98  ros::Publisher dummy_pub = n.advertise<nmea_msgs::Sentence>("nmea_sentence", 5);
99  ros::Subscriber dummy_sub = n.subscribe<nmea_msgs::Sentence>("nmea_sentence_out", 5, msg_callback);
100 
101  // Now start listening for the clients, here
102  // process will go in sleep mode and will wait
103  // for the incoming connection
104  listen(listener_fd, 5);
105 
106  unsigned int clilen = sizeof(cli_addr);
107 
108  ROS_INFO("Now listening for connections on port %d.", port);
109  struct pollfd pollfds[] = { { listener_fd, POLLIN, 0 } };
110  while (ros::ok())
111  {
112  int retval = poll(pollfds, 1, 500);
113  if (retval > 0)
114  {
115  int new_client_fd = accept(listener_fd, (struct sockaddr *) &cli_addr, &clilen);
116  if (new_client_fd < 0)
117  {
118  // Error of some kind?
119  }
120  else
121  {
122  rx_thread_start(n, new_client_fd, frame_id);
123  }
124  }
125  else
126  {
127  // just in case
128  ros::Duration(0.2).sleep();
129  }
130  }
131 
132  rx_stop_all();
133 
134  close(listener_fd);
135  return 0;
136 }
void msg_callback(const nmea_msgs::SentenceConstPtr sentence_msg_ptr)
Definition: socket_node.cpp:37
#define ROS_FATAL(...)
int main(int argc, char **argv)
Definition: socket_node.cpp:43
void rx_thread_start(ros::NodeHandle &n, int fd, std::string frame_id, uint32_t byte_time_ns=0)
Definition: rx.cpp:236
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void rx_stop_all()
Definition: rx.cpp:213
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void shutdown()
#define ROS_ERROR(...)


nmea_comms
Author(s): Mike Purvis
autogenerated on Mon Aug 5 2019 03:53:18