赞
踩
三、结合前两次的实验,实现linux和windoes下的socket通信
1.跨系统通信;并且结合ROS下的话题通信,在收到相关话题后,通过socket向windows下的服务端发送指定的信息
3.代码
server.cpp (windows)
- #include<WinSock2.h>
- #include<iostream>
- #include<string>
- using namespace std;
-
- #pragma comment(lib,"ws2_32.lib")
-
- int main(int arg, char* argv[])
- {
- cout << "Socket服务端" << endl;
-
- //初始化DLL
- WORD sockVersion = MAKEWORD(2, 2);
- WSADATA wsdata;
- if (WSAStartup(sockVersion, &wsdata) != 0)
- {
- return 1;
- }
-
- //创建套接字
- SOCKET serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
- //绑定套接字
- sockaddr_in server_addr;
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(10000);
- server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
- bind(serversocket, (sockaddr*)&server_addr, sizeof(server_addr));
-
- //建立通信套接字标识符
- SOCKET clientsocket;
- sockaddr_in client_addr;
- int len = sizeof(client_addr);
-
- while (true)
- {
- if (listen(serversocket, 5) == SOCKET_ERROR)
- {
- cout << "Bind Error" << endl;
- break;
- }
-
- //建立连接
- clientsocket = accept(serversocket, (sockaddr*)&client_addr, &len);
- if (clientsocket != INVALID_SOCKET)
- {
- cout << "连接到:" << inet_ntoa(client_addr.sin_addr) << endl;
- }
-
- //进入接收消息循环
- char msg[100];//接收消息缓冲区
- string check;
- check = "a";
- const char *ch;
- ch = check.c_str();
-
- while (true)
- {
- int num = recv(clientsocket, msg, 100, 0);
- if (num > 0)
- {
- msg[num] = '\0';
- cout << "客户端:" << msg << endl;
- send(clientsocket, ch, strlen(ch), 0);
- }
- else
- {
- break;
- }
- }
-
- }
-
- closesocket(clientsocket);
- closesocket(serversocket);
- WSACleanup();
-
- return 0;
- }
client.cpp (ubuntu)
- #include <ros/ros.h>
- #include <std_msgs/String.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <string>
- #include <iostream>
- #include <unistd.h>
-
-
- using namespace std;
-
- #define port 10000
- const char* _ip;
-
- int clientsocket;
- int i=0;
- sockaddr_in client_addr;
- string order="ok";
-
-
- void chatterCallback(const std_msgs::String::ConstPtr& msg)
- {
-
- ROS_INFO("listener is receiving [%s]", msg->data.c_str());
- //发送指令
- send (clientsocket,(char*)order.c_str(),order.length(),0);
- }
-
- int main (int argc,char **argv)
- {
-
- cout<<"socket客户端"<<endl;
- cout <<"请输入主机ip地址:"<<endl;
- string ip;
- cin>>ip;
- _ip=ip.c_str();
-
- //创建套接字
- clientsocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- client_addr.sin_family=AF_INET;
- client_addr.sin_port=htons(port);
- client_addr.sin_addr.s_addr=inet_addr(_ip);
-
- int check=connect(clientsocket,(sockaddr*)&client_addr,sizeof(client_addr));
- if(check<0)
- {
- cout<<"连接失败"<<endl;
- cout<<"请先开启服务器"<<endl;
- }
- else
- {
- cout<<"连接成功"<<endl;
- }
-
-
- //初始化节点
- ros::init(argc,argv,"listener");
- ros::NodeHandle n;
-
- //创建订阅者
- ros::Subscriber sub=n.subscribe("chatter", 1000, chatterCallback);
- ros::spin(); //程序进入循环,直到ros::ok()返回false,进程结束。
-
-
- close(clientsocket);
- return 0;
-
- }
以上订阅的“chatter”话题,时自己写的一个实验话题,只是发送一段字符串
talker.cpp
- #include <iostream>
- #include "ros/ros.h"
- #include "std_msgs/String.h"
-
- int main(int argc, char **argv)
- {
- //ros节点初始化 "talker"节点名称,在ROS里同一时间不允许出现两个
- ros::init(argc,argv,"talker");
- //创建节点句柄
- ros::NodeHandle h;
- //创建一个publisher, topic:chatter,消息类型std_msgs::String
- ros::Publisher chatter_pub = h.advertise<std_msgs::String>("chatter",1000); // "chatter"话题名称,消息缓存
- //设置单循环的频率
- ros::Rate looprate(0.5);
-
-
-
- while (ros::ok())
- {
- std_msgs::String msg;
- std::stringstream ss;
- ss<<"zzzzzzzz";
- msg.data = ss.str();
- //发布消息
- ROS_INFO("%s",msg.data.c_str());
- chatter_pub.publish(msg);
- //等待回调函数
- ros::spinOnce();
- //按照之前设定的进行循环
- looprate.sleep();
- }
-
- }
4.出现的问题,服务器中的listern()和accept()写在循环中,但是client中的connect写在循环外,最后导致只能收发一次,一直以为是client中的send()函数存在问题,最后检查send()函数的返回值才发现,是服务器的问题。以后调试代码时,要记得检查函数的返回值来判断问题。
5.以上实验成功后,将订阅的话题更改为turtlebot2中的到达目标点,来达到最终的目标
movebase_socket.cpp
- #include <ros/ros.h>
- #include <std_msgs/String.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <string>
- #include <iostream>
- #include <unistd.h>
- #include <move_base_msgs/MoveBaseAction.h>
- #include <move_base_msgs/MoveBaseActionGoal.h>
-
- using namespace std;
-
- #define port 10000
- const char* _ip;
-
- int clientsocket;
- int i=0;
- sockaddr_in client_addr;
- string order="ok";
-
- void chatterCallback(const move_base_msgs::MoveBaseActionResult& msg)
- {
- //发送指令
- if (msg.status.status==3)
- {
- cout <<"到达目标点"<<endl;
- send (clientsocket,(char*)order.c_str(),order.length(),0);
-
- }
- }
-
- int main (int argc,char **argv)
- {
-
- cout<<"socket客户端"<<endl;
- cout <<"请输入主机ip地址:"<<endl;
- string ip;
- cin>>ip;
- _ip=ip.c_str();
-
- //创建套接字
- clientsocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- client_addr.sin_family=AF_INET;
- client_addr.sin_port=htons(port);
- client_addr.sin_addr.s_addr=inet_addr(_ip);
-
- int check=connect(clientsocket,(sockaddr*)&client_addr,sizeof(client_addr));
- if(check<0)
- {
- cout<<"连接失败"<<endl;
- cout<<"请先开启服务器"<<endl;
- }
- else
- {
- cout<<"连接成功"<<endl;
- }
-
-
- //初始化节点
- ros::init(argc,argv,"get_status");
- ros::NodeHandle n;
-
- //创建订阅者
- ros::Subscriber sub=n.subscribe("move_base/result", 10, chatterCallback);
- ros::spin(); //程序进入循环,直到ros::ok()返回false,进程结束。
-
-
- close(clientsocket);
- return 0;
-
- }
订阅“move_base/result”话题,消息类型为move_base_msgs/MoveBaseActionResult
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。