Socket 学习 3

Socket通信学习 (自用笔记)

三、结合前两次的实验,实现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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值