实现ROS与服务器之间的socket通信学习笔记

Step1:
     通过ps aux查看进程PID号,再进入/pro/PID号/fd文件夹下,使用ll查看进程的文件描述符。
     0表示标准输入文件,1表示标准输出文件。
Step2:
     传输方式:(一个是菜鸟驿站式,一个是面签式)
    流格式套接字:
        socket stream
        使用TCP协议
        面向连接:有特定的数据传输路线
        按顺序传输,因为设有缓冲区,所以接收和发送可以不是同步的
    数据报格式套接字:
        socket dgram
        使用UDP协议,多用于音频视频传输
        无连接:无特定的路线,但是能到达目标
        效率较高,接收与发送是同步的,当延迟比数据完整性更重要时使用
Step3:
     流格式套接字:
    在路由之间建立一条固定的信息传输通道,发送端发送数据包给接收端,等待接收端返回含有确认信息的数据包,得以发送下一个数据包,如果没有返回则再次发送。    
     无连接套接字:
    在路由间存在许多条传输线路,数据包可通过任何一条传输线路到达接收端,由于没有确认和传输线路的不稳定,会导致数据包的丢失。
Step4:
     TCP/IP模型:网络接口层、网络层、传输层、应用层
     两台计算机通信必须在同一层次
     每一层的功能必须相同
Step5:
     一个局域网具有一个IP
     一台电脑一个MAC地址(跟网卡关联)
     每个网络程序具有独一无二的端口号
     只知道IP和MAC可以把数据报发送给对应的目标电脑,但是无法进行通信,还需要端口号来确定所需要的网络服务
Step6:
    源码:
    服务器端:
        首先用socket函数创建套接字  
        再创建一个包含服务器ip地址、端口号的结构体
        通过bind绑定套接字与ip地址与端口
        用listen表示让套接字休眠,直到客户端发起请求唤醒
        accept接收客户端请求,感觉类似于回调函数中的ros::spin,执行到这就阻塞
    客户端:
        connect向服务器发送请求
        read从套接字文件中读取数据
Step7:
     函数解析
         bind(int sock,struct sockaddr *addr,socklen_t addrlen):
        sock:socket文件描述符,由socket()返回得到
        addr:sockaddr结构体变量指针,输入为sockaddr_in结构体变量,需要强制转换为sockaddr,sockaddr结构体把sockaddr_in中的地址类型、ip地址、端口都合并到了一起
        addrlen:为addr变量的大小,用sizeof可以得到        
    listen(int sock,int backlog):
        sock:同上
        backlog:请求队列最大长度,服务器正在处理当前客户端请求时,如果有新的请求进来,不会立即执行而是会进入请求队列中,当请求队列满了,客户端会收到ECONNREFUSED错误
    accept(int sock,struct sockaddr *addr,socklen_t *addrlen):
        第二个参数存放客户端ip+端口的地址信息
        accept返回一个新的套接字来和客户端通信
    write(int fd,const void *buf,size_t nbytes):
        fd:为要写入的文件的描述府,由accept返回值提供
        buf:为要写入数据的缓冲区地址
        nbytes:要写入数据的字节数
    read
        同上
    send(int sock,const char* buffer,int len,int flags):
        sock:为accept返回的新套接字
        buffer:需要发送的字符串数组的首地址
        len:字符串数组的长度
        flags:通常为0或者NULL
    recv(int sock,char* buffer,int len,int flags):
        同上
Step8:
     可以直接通过加入ros相关函数来使得socket成为ROS中的一个节点
     只需要在accept前(创建新的套接字)加while循环,服务器持续监听客户端的请求
Step9:
     通过参考ros发送串口的节点,发现串口发送的函数写在回调函数中,这样能使传进来的数据在同一个数据块中发送出去。
     在把socket通信模块放入回调函数中,但是发送和接受的数组不能继续放在main函数中,因此写了一个类,将数组写进私有变量,把回调函数作为成员函数,刚好解决了这个问题。用ros:spinOnce()而不用ros::spin()的原因是前者可以控制发送的周期,而后者不行。
     发送的数组为char型,但是输入的pose为double型,需要转换。方案是先利用std::to_string(double)函数转化为string型,再在字符串的末尾加‘\n’,再用.c_str()将string型转化为char型数组,再用strcpy将数组拷贝。
Step10:
     socket发送数据首先是服务器发送给输出缓冲区,然后是由输入缓冲区读入,最后才是客户端读取,输入输出缓冲区大小默认为8K
     输出:
         当输出的数据大于输出缓冲区剩余空间,send和recv会阻塞(暂停执行)直到缓冲区里的数据发送出去,有足够的空间,才会唤醒send/recv
         输出的数据如果大于缓冲区的总长,则会分批发送
     输入:
    首先检查输入的缓冲区,如果缓冲区没有数据则阻塞运行
    如果一次读取数据量小于输入缓冲区,则数据会在输入缓冲区内不断的积压直到recv再次读取
Step11:
     TCP建立连接时需要传输三个数据包(三次握手)
     第一次握手:
    服务器先执行到listen并阻塞,客户端创建socket并执行connect,向服务器发送带有SYN同步信号的数据包,并且随机给数据包附上序号,之后客户端进入SYN-SEND状态
     第二次握手:
    服务器收到数据包,检测到是带有SYN标志的“请求包“,服务器建立一个新的数据包,并附上新的序号,数据包中由SYN与ACK,SYN用来建立连接,ACK用来确认请求,ACK=一个数据包的序号+1,之后服务器进入SYN-RECV状态
     第三次握手:
    客户端收到服务器发送的数据包,检测到SYN和ACK,判断ACK是否为上个数据包序号+1,如果是,则建立新的数据包,包含SYN和ACK,ACK为服务器发送过来的数据报序号+1,之后客户端状态为ESTABLISED,之后服务器接收到数据包,并检测ACK,如果符合,服务器的状态也会变成ESTABLISED
Step12:
     普通传输过程:
    客户端发出带有数据和序号的包给服务器,服务器接收到数据包的序号,返回一个带有ACK码的数据包,ACK=数据包的序列号+传递的字节数+1。以此类推。
    如果两次传输之间超时,客户端会重新发送数据包。
Step13:
     TCP断开连接时需要传输四个数据包(四次握手)
     第一次握手:当客户端运行到close()时,向服务器发送FIN数据包,进入FIN_WAIT_1
     第二次握手:服务器收到FIN数据包,服务器进入CLOSE_WAIT状态,并将带有ack的数据包发送给客户端,客户端收到ack的包后,经过校验,进入FIN_WAIT_2状态,继续等待
     第三次握手:服务器准备好后,主动向客户端发送FIN包,客户端接收到后进入TIME_WAIT状态
     第四次握手:客户端发送ack包,服务器接收到后断开tcp

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ROS中,Socket通信是一种常用的话题通信方式。在Windows系统中,可以使用ROS的Windows版本,例如ROS for Windows,来实现Socket通信。 首先,需要安装ROS for Windows,并设置好环境变量。然后,在ROS工作空间中创建一个Package,用于实现Socket通信。在Package的src文件夹下,创建一个节点文件,例如listener.cpp,用于接收Socket数据。 在listener.cpp中,可以使用ROS提供的Socket API来创建一个Socket进程,并绑定到一个特定的端口。然后,可以通过ROS的话题通信机制,将Socket数据发布到一个话题上。这样,其他节点就可以通过订阅该话题,获取到Socket数据。 在另一个节点中,可以创建一个发布者,用于将数据发送到特定的端口。该节点可以使用ROS提供的Socket API来创建一个Socket连接,并将数据发送到指定的端口。通过ROS的发布者,将发送的数据发布到一个话题上,其他节点可以通过订阅该话题,获取到发送的数据。 在ROS中,节点之间的通信主要通过话题、服务和参数服务器进行。话题通信是一种基于发布-订阅模式的通信方式,适用于多个节点之间的实时数据传输。而Socket通信则是一种基于网络的通信方式,可以实现不同设备之间的数据传输。 总之,通过使用ROS的Windows版本,可以很方便地实现Socket通信。这种通信方式可以在Windows系统下,实现不同节点之间的数据传输,为ROS在Windows平台上的应用提供了更多的灵活性和扩展性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值