Writing a Simple Service and Client (C++)

Writing a Simple Service and Client (C++)

Description: This tutorial covers how to write a service and client node in C++.

Tutorial Level: BEGINNER

Next Tutorial: Examining the simple service and client

Writing a Service Node

Here we'll create the service ("add_two_ints_server") node which will receive two ints and return the sum.

Change directory into the beginner_tutorials package, you created in the earlier tutorial, creating a package::

roscd beginner_tutorials

Please make sure you have followed the directions in the previous tutorial for creating the service needed in this tutorial, creating the AddTwoInts.srv.

The Code

Create the src/add_two_ints_server.cpp file within the beginner_tutorials package and paste the following inside it:


   1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 
   4 bool add(beginner_tutorials::AddTwoInts::Request  &req,
   5          beginner_tutorials::AddTwoInts::Response &res )
   6 {
   7   res.sum = req.a + req.b;
   8   ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
   9   ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  10   return true;
  11 }
  12 
  13 int main(int argc, char **argv)
  14 {
  15   ros::init(argc, argv, "add_two_ints_server");
  16   ros::NodeHandle n;
  17 
  18   ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  19   ROS_INFO("Ready to add two ints.");
  20   ros::spin();
  21 
  22   return 0;
  23 }
The Code Explained

Now, let's break the code down.


   1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 

beginner_tutorials/AddTwoInts.h is the header file generated from the srv file that we created earlier.


   4 bool add(beginner_tutorials::AddTwoInts::Request  &req,
   5          beginner_tutorials::AddTwoInts::Response &res )

This function provides the service for adding two ints, it takes in the request and response type defined in the srv file and returns a boolean.


   6 {
   7   res.sum = req.a + req.b;
   8   ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
   9   ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  10   return true;
  11 }

Here the two ints are added and stored in the response. Then some information about the request and response are logged. Finally the service returns true when it is complete.


  18   ros::ServiceServer service = n.advertiseService("add_two_ints", add);

Here the service is created and advertised over ROS.

Writing the Client Node

The Code

Create the src/add_two_ints_client.cpp file within the beginner_tutorials package and paste the following inside it:


   1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 #include <cstdlib>
   4 
   5 int main(int argc, char **argv)
   6 {
   7   ros::init(argc, argv, "add_two_ints_client");
   8   if (argc != 3)
   9   {
  10     ROS_INFO("usage: add_two_ints_client X Y");
  11     return 1;
  12   }
  13 
  14   ros::NodeHandle n;
  15   ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
  16   beginner_tutorials::AddTwoInts srv;
  17   srv.request.a = atoll(argv[1]);
  18   srv.request.b = atoll(argv[2]);
  19   if (client.call(srv))
  20   {
  21     ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  22   }
  23   else
  24   {
  25     ROS_ERROR("Failed to call service add_two_ints");
  26     return 1;
  27   }
  28 
  29   return 0;
  30 }
The Code Explained

Now, let's break the code down.


  15   ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");

This creates a client for the add_two_ints service. The ros::ServiceClient object is used to call the service later on.


  16   beginner_tutorials::AddTwoInts srv;
  17   srv.request.a = atoll(argv[1]);
  18   srv.request.b = atoll(argv[2]);

Here we instantiate an autogenerated service class, and assign values into its request member. A service class contains two members, request and response. It also contains two class definitions, Request and Response.


  19   if (client.call(srv))

This actually calls the service. Since service calls are blocking, it will return once the call is done. If the service call succeeded, call() will return true and the value in srv.response will be valid. If the call did not succeed, call() will return false and the value in srv.response will be invalid.

Building your nodes

Again edit the beginner_tutorials CMakeLists.txt:

$ rosed beginner_tutorials CMakeLists.txt 

and add the following at the end:

rosbuild_add_executable(add_two_ints_server src/add_two_ints_server.cpp)
rosbuild_add_executable(add_two_ints_client src/add_two_ints_client.cpp)

This will create two executables, "add_two_ints_server" and "add_two_ints_client", which by default will go into the "bin" directory.

For more information on using CMake with ROS, see CMakeLists Now run make:

$ make

If your build fails for some reason:

  • make sure you have followed the directions in the previous tutorial: creating the AddTwoInts.srv.

  • type rosls beginner_tutorials/srv_gen/cpp/include/beginner_tutorials/ and check that the .h file matches the include in the client and server .cpp files.

Now that you have written a simple service and client, let's examine the simple service and client.
以下是一个使用C语言编写的简单HTTP客户端,具有基本的GET和POST请求功能。它使用了标准C库中的socket和unistd库函数。 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFFER_SIZE 1024 int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char buffer[BUFFER_SIZE]; if (argc < 4) { fprintf(stderr, "usage %s hostname port path\n", argv[0]); exit(0); } portno = atoi(argv[2]); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("ERROR opening socket"); exit(1); } server = gethostbyname(argv[1]); if (server == NULL) { fprintf(stderr, "ERROR, no such host\n"); exit(0); } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("ERROR connecting"); exit(1); } // send GET request sprintf(buffer, "GET %s HTTP/1.0\r\n\r\n", argv[3]); n = write(sockfd, buffer, strlen(buffer)); if (n < 0) { perror("ERROR writing to socket"); exit(1); } // receive response bzero(buffer, BUFFER_SIZE); while ((n = read(sockfd, buffer, BUFFER_SIZE - 1)) > 0) { printf("%s", buffer); bzero(buffer, BUFFER_SIZE); } if (n < 0) { perror("ERROR reading from socket"); exit(1); } // send POST request sprintf(buffer, "POST %s HTTP/1.0\r\nContent-Length: 5\r\n\r\nhello", argv[3]); n = write(sockfd, buffer, strlen(buffer)); if (n < 0) { perror("ERROR writing to socket"); exit(1); } // receive response bzero(buffer, BUFFER_SIZE); while ((n = read(sockfd, buffer, BUFFER_SIZE - 1)) > 0) { printf("%s", buffer); bzero(buffer, BUFFER_SIZE); } if (n < 0) { perror("ERROR reading from socket"); exit(1); } close(sockfd); return 0; } ``` 该程序通过命令行参数接收主机名,端口号和路径,然后使用socket函数创建一个TCP套接字并连接到指定主机和端口。接下来,它使用sprintf函数构造GET和POST请求,并使用write函数将其写入套接字。最后,它使用read函数读取套接字中的响应,并将其打印到标准输出上。 请注意,此代码仅用于演示目的,并且没有处理错误或异常情况。在实际应用程序中,您需要添加错误处理和异常处理代码。此外,该代码仅支持HTTP/1.0协议,并且不支持HTTPS。如果您需要更复杂的HTTP客户端功能,您可能需要使用现有的HTTP客户端库,例如libcurl或http-parser。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值