当前位置:   article > 正文

鸿蒙源码分析(十九)_鸿蒙软总线源码分析

鸿蒙软总线源码分析


coap_socket.c代码分析

本篇主题:本篇博客主要分析coap_socket.c相关代码
文件路径(软总线模块\discovery\coap\source\coap_socket.c)

一、背景知识

socket通信机制详解

二、coap_socket.c代码详细分析

该文件中主要分为三部分,分别为套接字的获取,socket两端(客户端、服务器)的创建,数据的发送和接收。

2.1 套接字的获取

这一部分主要使用函数来返回用户定义的全局变量g_serverFd、g_clientFd。实现套接字的获取

int g_serverFd = -1;//全局服务器套接字
int g_clientFd = -1;//客户端套接字

//用来获取coap服务器的套接字g_serverFd
int GetCoapServerSocket(void)
{
    return g_serverFd;
}
//用来获取coap客户端的套接字g_clientFd
int GetCoapClientSocket(void)
{
    return g_clientFd;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.2 socket两端(客户端、服务器)的创建

下面两部分代码主要实现客户端的创建和服务器的创建。
基于udp协议服务器的创建
该函数主要用来创建一个基于udp协议的服务器,而非trans_service下面的TCP协议。
实现套接字的创建和端口绑定(bind())的过程。

//创建一个服务器,传输协议为udp而非tcp
int CoapCreateUdpServer(const struct sockaddr_in *sockAddr)
{
    if (sockAddr == NULL) {
        return NSTACKX_EINVAL;
        //检查传入的啊承诺书是否为空
    }
    struct sockaddr_in localAddr;//本地地址结构体
    socklen_t len = sizeof(localAddr);//
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建一个套接字
    if (sockfd < 0) {
        return NSTACKX_OVERFLOW;
    }

    (void)memset_s(&localAddr, sizeof(localAddr), 0, sizeof(localAddr));
    //对localAddr进行初始化
    localAddr.sin_family = AF_INET; //用来保存本地的地址族
    localAddr.sin_port = sockAddr->sin_port;//存放sock地址的端口
    if (sockAddr->sin_addr.s_addr != 0) {
        //如果端口的s_addr不为0
        localAddr.sin_addr.s_addr = sockAddr->sin_addr.s_addr;
        //将sockaddr的s_addr写进localAttr
    } else {
        //s_addr为0,则localAttr对应的s_addr为htonl获取的地址
        localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    //将sockfd和localAddr相关联的端口设备进行绑定
    if (bind(sockfd, (struct sockaddr *)&localAddr, len) == -1) {
        CloseSocket(&sockfd);
        //绑定失败就关闭套接字
        return NSTACKX_EFAILED;
    }

    if (getsockname(sockfd, (struct sockaddr *)&localAddr, &len) == -1) {
        //获取套接字的名字,获取失败就关闭套接字
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
    }
    return sockfd;//最后返回所连接套接字
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

基于udp协议的客户端创建
该函数主要用来创建一个基于udp协议的客户端,中间使用到临时地址,最后将创建成功的服务器套接字写进定义的全局变量g_clientFd。

//和上方创建服务器类似,这里创建一个客户端
int CoapCreateUdpClient(const struct sockaddr_in *sockAddr)
{
    if (sockAddr == NULL) {
        return NSTACKX_EFAILED;
    //用来检查传入的sockAddr
    }
    struct sockaddr_in tmpAddr;//定义一个临时的套接字地址
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建生成一个新的套接字sockfd
    if (sockfd < 0) {
        return NSTACKX_EFAILED;
        //创建失败的处理
    }

    int ret = connect(sockfd, (struct sockaddr *)sockAddr, sizeof(struct sockaddr));
    //根据所创建生成的套接字进行连接
    if (ret != 0) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
        //连接失败关闭套接字,函数返回
    }
    socklen_t srcAddrLen = sizeof(struct sockaddr_in);
    (void)memset_s(&tmpAddr, sizeof(tmpAddr), 0, sizeof(tmpAddr));
    //初始化临时的套接字地址,并获取临时套接字名字
    ret = getsockname(sockfd, (struct sockaddr *)&tmpAddr, &srcAddrLen);
    if (ret != 0) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
        //获取失败的处理
    }

    CloseSocket(&g_clientFd);
    //关闭临时客户端
    g_clientFd = sockfd;
    //并且将客户端套接字重置为新生成的套接字
    return NSTACKX_EOK;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

2.3 数据的接收和发送

发送数据基于CoapSocketSend()函数
该函数的主要原理是将数据传送至指定目的缓冲区,可以实现未连接状态下的数据发送。这里主要是发送到socket->dstAddr对应的目的地缓冲区
sendto()函数参数详解:

  • s 套接字
  • buff 待发送数据的缓冲区
  • size 缓冲区长度
  • Flags 调用方式标志位, 一般为0, 改变Flags,将会改变Sendto发送的形式
  • addr (可选)指针,指向目的套接字的地址
  • len addr所指地址的长度
//用来将数据发送到udp连接的另一端
int CoapSocketSend(const SocketInfo *socket, const uint8_t *buffer, size_t length)
{
    if (buffer == NULL || socket == NULL) {
        return NSTACKX_EFAILED;
    }

    socklen_t dstAddrLen = sizeof(struct sockaddr_in);
    int ret = sendto(socket->cliendFd, buffer, length, 0, (struct sockaddr *)&socket->dstAddr, dstAddrLen);
    //sendto用来发送udp数据包,这里发送到ocket->dstAddr目的地缓冲区
    return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接收数据基于CoapSocketRecv()函数
该函数主要实现数据的接收,基于recvfrom()函数接收远程主机经指定的socket传来的数据,并把数据传到由参数buf指向的内存空间,参数len为可接收数据的最大长度.参数flags一般设0,其他数值定义参考recv().参数from用来指定欲传送的网络地址,结构sockaddr请参考bind()函数.参数fromlen为sockaddr的结构长度。
recvfrom()函数参数详解:

  • socketfd 套接字
  • buffer 存放接收的数据
  • len 可接收数据的最大长度
//用来接收数据经过socket
int CoapSocketRecv(int socketFd, uint8_t *buffer, size_t length)
{
    if (buffer == NULL || socketFd < 0) {
        return NSTACKX_EFAILED;
        //参数检查
    }
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr_in);
    (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
    //初始化addr缓冲区
    int ret = recvfrom(socketFd, buffer, length, 0, (struct sockaddr *)&addr, &len);
    //recvfrom函数用来接收指定socket传来的数据
    return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

三、总结

以上就是coap_socket.c的内容,简单介绍了该文件中代码结构和原理。感谢阅读和点赞。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/325041
推荐阅读
相关标签
  

闽ICP备14008679号