Socket通信实践

27 篇文章 1 订阅
14 篇文章 4 订阅

1、获取HostInfo

get_host_info.h

#include <arpa/inet.h> 
#include <netdb.h>    
#include <unistd.h>   

bool getHostInfo(std::string& host_name, std::string& ip)
{
    char name[256];
    gethostname(name, sizeof(name));
    host_name = name;
    struct hostent* host = gethostbyname(name);
    char ipStr[32];
    const char* ret =
        inet_ntop(host->h_addrtype, host->h_addr_list[0], ipStr, sizeof(ipStr));
    if (NULL == ret) {
      return false;
    }
    ip = ipStr;
    return true;
};

2、服务端Server

#include <sys/socket.h> 
#include <iostream>

#include "get_host_info.h"

int main()
{
    int port = 9100;
    std::string host_name,ip;
    if(!getHostInfo(host_name,ip)){
        return 0;
    }

    //创建套接字,绑定端口,IP
    int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));         
    server_addr.sin_family = AF_INET;                              
    server_addr.sin_addr.s_addr = inet_addr(ip.c_str());            
    server_addr.sin_port = htons(port);                    
    bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));

    //进入监听状态,等待用户发起请求
    if (listen(server_socket, 20)) {return 0;}

    //在while循环内等待客户端的链接
    struct sockaddr_in client_addr;
    socklen_t client_addr_size = sizeof(client_addr);
    while(true)
    {
        //接收到客户端套接字,server会持续停留在下面这条语句,直到接收到客户端
        int client_sock = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_size);

        //一次成功链接,考试处理作出反应
        if (client_sock > 0) 
        {
          std::string recv_buffer = "";
          //一次成功链接后,会持续接受该客户端信息,直到客户端关闭,才会失去链接
          while(1)
          {
            //注意client发过来的信息可能很长,会切割成1024大小的片段发送,所以需要多次接受
            char buffer[1024];      
            memset(buffer,0,sizeof(buffer));
            int len = recv(client_sock,buffer,sizeof(buffer),0);
            if(len <= 0)break;
            recv_buffer += std::string(buffer);                  
          }
          if(recv_buffer == ""){continue;}
          //打印接收到的信息
          std::cout<<"receive info : "<<recv_buffer<<std::endl;
          //在这里也可以发送信息给client
        }
        close(client_sock);
    }
    close(server_socket);
    return 0;
}

3、客户端Client

#include <sys/socket.h> 
#include <iostream>
#include <ros/ros.h>

#include "get_host_info.h"

int main()
{
    //切片发送字符串的lambda函数
    auto sendString = [](int& socket, int step,std::string& send_str)
    {
      //计算待发送数据的长度
      int len = strlen(send_str.c_str());
      //发送数据
      for (int i = 0; i < len; i = i + step) {
        std::string str = send_str.substr(i, step);
        send(socket, str.c_str(), strlen(str.c_str()), 0);
        usleep(1);//中间需要有停顿,不可以一直发送,否则server接受会出现错乱
      }
      //发送一个空字符,server收到长度为0的字符后会停止接收
      std::string str = "";
      send(socket, str.c_str(), strlen(str.c_str()), 0);  
    };

    //获取HostInfo
    int port = 9100;
    std::string host_name,ip;
    if(!getHostInfo(host_name,ip)){return 0;}

    //在while循环内持续创建套接字,并且发送信息
    while (true) {
      //创建客户端套接字
      int sock = socket(AF_INET, SOCK_STREAM, 0);
      //向服务器(特定的IP和端口)发起请求
      struct sockaddr_in serv_addr;
      memset(&serv_addr, 0, sizeof(serv_addr));           //每个字节都用0填充
      serv_addr.sin_family = AF_INET;                     //使用IPv4地址
      serv_addr.sin_addr.s_addr = inet_addr(ip.c_str());  //具体的IP地址
      serv_addr.sin_port = htons(port);          //端口

      //连接服务器
      //connect只会链接一次,不会一直等待
      if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        //std::cout << "can not connect socket" << std::endl;
        // exit(1);
      } else {
        //向server发送信息
        //发送当前的wall time给服务端
        ros::WallTime wall_time = ros::WallTime::now();
        std::string str = std::to_string(wall_time.toSec());
        sendString(sock, 1024, str);
      }
      close(sock);
      sleep(1);
    }  
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值