目录

1、前言

2、网关(转载)

3、基础知识

3.1 pthread线程库介绍(转载)

3.2 socket 简介

3.2.1 什么是网络、计算机网络的构成是什么?

3.2.2 什么是网络编程?

3.2.3 7层网络模型--OSI

3.2.4 网络模型---对应关系

​3.2.5 Socket与TCP、UDP

3.2.6 Socket的传输原理

3.3 socket编程(转载)

3.3.1 结构体

3.3.2 socket() 函数

3.4 互斥锁

3.5 信号量

4、线程

3.1 main(主线程)

3.2 thread_up(上行线程)

3.3 thread_down(下行线程)

3.4 thread_jit

3.5 thread_gps

3.6 thread_valid

3.7 thread_timersync


1、前言

如下图所示,lora_pkt_fwd.c是一个运行在 Lora Gateway Host上的程序,将Concentrator(集中器)接收到的无线数据包通过 IP/UDP 转发到服务器链接,并发射由服务器发送的无线数据包。 它还可以发出用于协调所有节点的全网 GPS 同步信标信号网络。

((( Y )))||+- -|- - - - - - - - - - - - -+        xxxxxxxxxxxx          +--------+|+--+-----------+     +------+|       xx x  x     xxx        |        |||              |     |      ||      xx  Internet  xx        |        ||| Concentrator |<----+ Host |<------xx     or    xx-------->|        |||              | SPI |      ||      xx  Intranet  xx        | Server ||+--------------+     +------+|       xxxx   x   xxxx        |        ||   ^                    ^    |           xxxxxxxx           |        ||   | PPS  +-----+  NMEA |    |                              |        ||   +------| GPS |-------+    |                              +--------+|          +-----+            ||                             ||            Gateway          |+- - - - - - - - - - - - - - -+

Concentrator:radio RX/TX board, based on Semtech multichannel modems 
(SX130x), transceivers (SX135x) and/or low-power stand-alone modems (SX127x).

(无线电 RX/TX 板,基于 Semtech 多通道调制解调器(SX130x)、收发器 (SX135x) 和/或低功耗独立调制解调器 (SX127x))

Host:embedded computer on which the packet forwarder is run. Drives the 
concentrator through a SPI link.

(运行数据包转发器的嵌入式计算机。 驱动集中器通过 SPI 链接)

GPS: GNSS (GPS, Galileo, GLONASS, etc) receiver with a "1 Pulse Per Second"
output and a serial link to the host to send NMEA frames containing time and
geographical coordinates data. Optional.

(具有“每秒 1 个脉冲”的 GNSS(GPS、Galileo GLONASS 等)接收器输出和到主机的串行链路以发送包含时间和地理坐标数据。 可选的)

Gateway: a device composed of at least one radio concentrator, a host, some 
network connection to the internet or a private network (Ethernet, 3G, Wifi, 
microwave link), and optionally a GPS receiver for synchronization.

(由至少一个无线电集中器、一个主机、一些到互联网或专用网络的网络连接(以太网、3G、Wifi、微波链接),以及可选的 GPS 接收器用于同步。)

Server: an abstract computer that will process the RF packets received and 
forwarded by the gateway, and issue RF packets in response that the gateway 
will have to emit.

(一个抽象的计算机,它将处理接收到的 RF 数据包和由网关转发,并发出 RF 数据包以响应网关
将不得不发射。)


2、网关(转载)

网关的学习_ycxzz的博客-CSDN博客一 网关的定义       网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的https://blog.csdn.net/ycxzz/article/details/79191827?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-13.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-13.no_search_link


3、基础知识

3.1 pthread线程库介绍(转载)

linux多线程pthread系列函数详解 - 开心happy - 博客园linux多线程pthread系列函数详解 (一)为什么要引入线程 线程技术早在60年代就被提出,但是在80年代才真正使用到操作系统中。传统UNIX也支持多线程概念,但在一个进程中只允许有一个线程,这https://www.cnblogs.com/minihaohao/p/5188906.html

3.2 socket 简介

以下来自CSDN博主「折腾java」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:什么是网络编程(一)_折腾java的博客-CSDN博客_网络编程

3.2.1 什么是网络、计算机网络的构成是什么?

在计算领域中,网络是传输信息、接受、共享的虚拟的平台。通过它可以把各个点、面、体的信息联系到一起,从而实现这些资源的共享。网络是人类发展史上最重要的发明,提高了人类和科技的一个发展。

3.2.2 什么是网络编程?

网络编程从大的方面就是说对信息的发送接收。

通过操作相应API调度计算机资源硬件,并且利用管道(网线)进行数据交互的过程。

更为具体的涉及:网络模型、套接字、数据包。

3.2.3 7层网络模型--OSI

基础层:物理层(physical)、数据链路层(Datalink)、网络层(network).。

传输层(Transport):TCP-UDP协议层、Socket。

高级层::会话层(Session)、表示层(Presentation)、应用层(Application)

3.2.4 网络模型---对应关系

3.2.5 Socket与TCP、UDP

Socket:简单来说是ip地址与端口的结合协议(RFC 793).

一种地址与端口的结合描述协议。

TCP/IP协议的相关API的总称;是网络API的集合实现.

涵盖了Stream socket /Datagram Socket

socket 的组成与作用:

在网络传输中用于唯一标识两个端点的链接。

端点:包括(ip+port)

4个要素:客户端的地址、客户端的端口、服务器的地址、服务器端口。

3.2.6 Socket的传输原理

Socket之TCP:

tcp是面向连接的通讯协议。

通过三次握手建立连接,通讯完成时要拆除连接。

由于TCP是面向连接的,所以只能用于端到端的通信。

Socket之UDP:

UDP是面向无连接进行通讯的。

UDP数据包括目的端口号和源端口号信息。

由于通讯时是不需要连接,所以可以是实现广播发送,并不局限于端到端。

3.3 socket编程(转载)

socket编程入门:1天玩转socket通信技术(非常详细)socket编程也叫套接字编程,这套socket入门教程将为你讲解socket通信的相关技术。本教程通俗易懂、深入浅出,你将很容易掌握socket套接字编程技巧。http://c.biancheng.net/socket/

3.3.1 结构体

struct sockaddr

{

  unsigned short sa_family;

char sa_data[14];

};

1、sa_family 为调用socket()时的domain 参数, 即AF_xxxx 值。AF为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。

2、sa_data 为14字节的协议地址,包含该socket的IP地址和端口号。

注:此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息,sockaddr 结构会因使用不同的socket domain 而有不同结构定义。

3.3.2 socket() 函数

1)creates  an  endpoint  for  communication and returns a descriptor

int socket (int domain, int type, int protocol);

domain 参数指定一个通信域; 这个选择将用于通信的协议族。这些系列在 <sys/socket.h> 中定义。 目前可理解的格式包括:

       Name                Purpose                              Man pageAF_UNIX, AF_LOCAL   Local communication                  unix(7)AF_INET             IPv4 Internet protocols              ip(7)AF_INET6            IPv6 Internet protocols              ipv6(7)AF_IPX              IPX - Novell protocolsAF_NETLINK          Kernel user interface device         netlink(7)AF_X25              ITU-T X.25 / ISO-8208 protocol       x25(7)AF_AX25             Amateur radio AX.25 protocolAF_ATMPVC           Access to raw ATM PVCsAF_APPLETALK        AppleTalk                            ddp(7)AF_PACKET           Low level packet interface           packet(7)AF_ALG              Interface to kernel crypto API

type参数为套接字指定类型,它指定了通信语义。 当前定义的类型有:

       SOCK_STREAM     提供基于顺序的、可靠的、双向的、连接的字节流。 SOCK_DGRAM      支持数据报(无连接、不可靠固定最大长度的消息)。SOCK_SEQPACKET  基于数据报提供有序、可靠的、双向连接的数据传输路径固定最大长度。SOCK_RAW        提供原始网络协议访问。SOCK_RDM        提供不保证排序的可靠数据报层。

protocol 指定要与套接字一起使用的特定协议。 通常,在给定的protocol 族中,只有一个协议支持特定的套接字类型,在这种情况下,protocol 可以指定为 0。但是,可能存在许多协议,在这种情况下,必须指定一个特定的protocol 。

2) bind a name to a socket  (为套接字分配名称)

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind() 将 addr 指定的地址分配给文件描述符 sockfd 引用的套接字。addrlen 指定 addr 指向的地址结构的大小(以字节为单位)此操作称为“为套接字分配名称”。

3)initiate a connection on a socket (在套接字上启动连接)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

connect() 调用后系统将文件描述符 sockfd 引用的套接字连接到 addr 指定的地址。addrlen 参数指定 addr 的大小。addr中地址的格式由socket sockfd的地址空间决定。

4)listen for connections on a socket (侦听套接字上的连接)

int listen(int sockfd, int backlog);
listen() 将 sockfd 引用的套接字标记为被动套接字,用于接受即将传入的套接字,使用accept() 的连接请求。

sockfd 参数是引用套接字的文件描述符:SOCK_STREAM 或 SOCK_SEQPACKET 类型。

backlog 参数定义了 sockfd 的挂起连接队列可以增长到的最大长度。 如果连接请求在队列已满时到达,客户端可能会收到一个带有 ECONNREFUSED 指示的错误,或者,如果底层协议支持重传,则该请求可能会被忽略,以便稍后重新尝试连接成功。

5)accept a connection on a socket (接受套接字上的连接)

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept() 与基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)一起使用。它从侦听套接字 sockfd 的挂起连接队列中提取第一个连接请求,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符。新创建的套接字未处于侦听状态。原始套接字 sockfd 不受此调用的影响。

参数 sockfd 是一个使用 socket() 创建的套接字,使用 bind() 绑定到本地地址,并在 listen() 之后监听连接。

参数 addr 是指向 sockaddr 结构的指针。这个结构用通信层已知的对等套接字的地址填充。返回 addr 的地址的确切格式,由套接字的地址系列决定。当addr为NULL时,什么都不填;在这种情况下,addrlen 未使用,也应为 NULL。

addrlen 参数是一个 value-result 参数:调用者必须初始化它以包含 addr 指向的结构的大小(以字节为单位);返回时,它将包含对等地址的实际大小。

6)get and set options on sockets (获取和设置套接字上的选项)

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
参数sockfd:是一个使用 socket() 创建的套接字返回的文件描述符
参数level:协议层次
                    SOL_SOCKET 套接字层次
                    IPPROTO_IP ip层次
                    IPPROTO_TCP TCP层次
参数optname:选项的名称(套接字层次)
                   SO_BROADCAST 是否允许发送广播信息
                   SO_REUSEADDR 是否允许重复使用本地地址
                   SO_SNDBUF 获取发送缓冲区长度
                   SO_RCVBUF 获取接收缓冲区长度                                                                                     SO_RCVTIMEO 获取接收超时时间
                   SO_SNDTIMEO 获取发送超时时间                                                                             参数optval:指针,指向获取到的选项的缓冲区
 参数optlen:指针,指向optval缓冲区的长度
 返回值:成功:0  失败:-1

3.4 互斥锁

3.5 信号量


4、线程

在文件lora_pkt_fwd.c中,man()里面创建了6个线程来实现如下功能:

  1. 周期性地从concentrator中取出报文封装无线数据包(PUSH_DATA )并通过UDP传输至互联网上的 LoRa 网关(上行)。
  2. 接受server下行应用报文,
  3. 接收GPS位置和时间

3.1 main(主线程)

1、加载配置文件:全局配置还是局部配置还是调试配置

if (access(debug_cfg_path, R_OK) == 0) { /* if there is a debug conf, parse only the debug conf如果有调试配置,只解析调试配置 */MSG("INFO: found debug configuration file %s, parsing it\n", debug_cfg_path);MSG("INFO: other configuration files will be ignored\n");x = parse_SX1301_configuration(debug_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}x = parse_gateway_configuration(debug_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}} else if (access(global_cfg_path, R_OK) == 0) { /* if there is a global conf, parse it and then try to parse local conf  */MSG("INFO: found global configuration file %s, parsing it\n", global_cfg_path);x = parse_SX1301_configuration(global_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}x = parse_gateway_configuration(global_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}if (access(local_cfg_path, R_OK) == 0) {MSG("INFO: found local configuration file %s, parsing it\n", local_cfg_path);MSG("INFO: redefined parameters will overwrite global parameters\n");parse_SX1301_configuration(local_cfg_path);parse_gateway_configuration(local_cfg_path);}} else if (access(local_cfg_path, R_OK) == 0) { /* if there is only a local conf, parse it and that's all */MSG("INFO: found local configuration file %s, parsing it\n", local_cfg_path);x = parse_SX1301_configuration(local_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}x = parse_gateway_configuration(local_cfg_path);if (x != 0) {exit(EXIT_FAILURE);}} else {MSG("ERROR: [main] failed to find any configuration file named %s, %s OR %s\n", global_cfg_path, local_cfg_path, debug_cfg_path);exit(EXIT_FAILURE);}

2、启动GPS

if (gps_tty_path[0] != '\0') { /* do not try to open GPS device if no path set */i = lgw_gps_enable(gps_tty_path, "ubx7", 0, &gps_tty_fd); /* HAL only supports u-blox 7 for now */if (i != LGW_GPS_SUCCESS) {printf("WARNING: [main] impossible to open %s for GPS sync (check permissions)\n", gps_tty_path);gps_enabled = false;gps_ref_valid = false;} else {printf("INFO: [main] TTY port %s open for GPS synchronization\n", gps_tty_path);gps_enabled = true;gps_ref_valid = false;}}

3、地址转换,将主机物理地址转换成网络字节顺序地址

net_mac_h = htonl((uint32_t)(0xFFFFFFFF & (lgwm>>32)));
net_mac_l = htonl((uint32_t)(0xFFFFFFFF &  lgwm  ));

4、创建网络套接字socket进行通信

i = getaddrinfo(serv_addr, serv_port_up, &hints, &result);
...
for (q=result; q!=NULL; q=q->ai_next) {sock_up = socket(q->ai_family, q->ai_socktype,q->ai_protocol);if (sock_up == -1) continue; /* try next field */else break; /* success, get out of loop */}if (q == NULL) {MSG("ERROR: [up] failed to open socket to any of server %s addresses (port %s)\n", serv_addr, serv_port_up);i = 1;for (q=result; q!=NULL; q=q->ai_next) {getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST);MSG("INFO: [up] result %i host:%s service:%s\n", i, host_name, port_name);++i;}exit(EXIT_FAILURE);}i = connect(sock_up, q->ai_addr, q->ai_addrlen);if (i != 0) {MSG("ERROR: [up] connect returned %s\n", strerror(errno));exit(EXIT_FAILURE);}freeaddrinfo(result);

5、启动集中器

i = lgw_start();

6、创建4个线程来管理上下行:thrid_up、thrid_down、thrid_jit、thrid_timersync

    i = pthread_create( &thrid_up, NULL, (void * (*)(void *))thread_up, NULL);i = pthread_create( &thrid_down, NULL, (void * (*)(void *))thread_down, NULL);i = pthread_create( &thrid_jit, NULL, (void * (*)(void *))thread_jit, NULL);i = pthread_create( &thrid_timersync, NULL, (void * (*)(void *))thread_timersync, NULL);

7、创建2个线程来管理GPS:thrid_gps、thrid_valid

     i = pthread_create( &thrid_gps, NULL, (void * (*)(void *))thread_gps, NULL);i = pthread_create( &thrid_valid, NULL, (void * (*)(void *))thread_valid, NULL);

8、信号量。

sigaction(SIGQUIT, &sigact, NULL); /* Ctrl-\ */
sigaction(SIGINT, &sigact, NULL); /* Ctrl-C */
sigaction(SIGTERM, &sigact, NULL); /* default "kill" command */

9、while循环。只要不是退出进程的信号,一直死循环的以默认的时间间隔收集和显示统计信息并发送给server

while (!exit_sig && !quit_sig) {wait_ms(1000 * stat_interval);/* wait for next reporting interval */

3.2 thread_up(上行线程)

3.3 thread_down(下行线程)

3.4 thread_jit

3.5 thread_gps

3.6 thread_valid

3.7 thread_timersync

学习笔记(1)lora_pkt_fwd.c (LoRaWAN Gateway核心代码)相关推荐

  1. amazeui学习笔记--css(HTML元素2)--代码Code

    amazeui学习笔记--css(HTML元素2)--代码Code 一.总结 1.行内代码:code标签<code> 2.代码片段:pre标签<pre> 3.限制代码块高度:添 ...

  2. JAVASE的学习笔记(四)(抽象类,代码块,接口)

    JAVASE的学习笔记(四) 抽象类与接口 JAVASE的学习笔记(四) 代码块 例题: 静态代码块 加载类的方法 手动加载类 抽象类(**只能被继承使用,自己应该无法创建对象**) 重要: 抽象类由 ...

  3. 影像组学视频学习笔记(7)-特征筛选之LASSO回归(代码)、Li‘s have a solution and plan.

    本笔记来源于B站Up主: 有Li 的影像组学系列教学视频 本节(7)主要介绍: 特征筛选之LASSO回归分析(代码实现) import pandas as pd import numpy as np ...

  4. 视觉学习笔记6——YOLOv5(v6.2)部署与代码理解

    文章目录 前言 一.YOLOv5是什么? 二.环境搭建 1.基本环境 2.特殊环境 三.自定义训练 模型训练 模型测试 四.源码个人理解 1.detect.py文件 2.yolo.py文件 3. tr ...

  5. 学习笔记(2):Java面试:核心考点突击大串讲-Redis的持久化机制

    立即学习:https://edu.csdn.net/course/play/29988/432570?utm_source=blogtoedu RDB默认三个配置 save 900 1 300 10 ...

  6. 学习笔记(1):Java面试:核心考点突击大串讲-JavaSE开胃面试题介绍

    立即学习:https://edu.csdn.net/course/play/29988/432515?utm_source=blogtoedu 概念类 JVM,JDK,JRE 基本数据类型和包装类 构 ...

  7. SharpDevelop学习笔记(4)——SharpDevelop的核心

    SharpDevelop的主要任务是加载和生成AddIn树.SD的核心程序由三个project 组成,即StartUp.ICSharpCode.SharpDevelop.ICSharpCode.Cor ...

  8. 《童虎学习笔记》5分钟了解Citus核心系统表

    本专栏全部文章 https://blog.csdn.net/tonghu_note/category_11713514.html 总目录 https://blog.csdn.net/tonghu_no ...

  9. 【学习笔记】 pytorch的使用语法和代码实例

    数据类型 ( 1) torch.FloatTensor : 用于生成数据类型为浮点型的Tensor ,传递给torch.FloatTensor的参数可以是一个列表,也可以是一个维度值. torch.r ...

最新文章

  1. Linux期末复习题库(4)
  2. center6linux ip设置,centos6固定ip地址
  3. 如何根据原理图画封装_常用原理图封装
  4. 在使用 Elasticsearch 时要注意什么?
  5. android 去掉顶部状态栏
  6. python计算auc的代码_python是怎么计算auc指标的?
  7. java 终止方法_Java中终止线程的三种方法
  8. 【Java项目实战】黄金矿工小游戏项目介绍
  9. plsql 64位连接oracle,Plsql连接Oracle 64位
  10. 安卓学习之路-RecyclerView的简单用法
  11. 计算机考证包括cad吗
  12. 英语单词词性顺口溜_英语单词词性分类
  13. JavaScript与C#互通的DES加解密算法
  14. C语言系列(11)——数组(02)
  15. 整理学习之深度迁移学习
  16. opengl 画椭圆_如何用彩铅画一朵牡丹?彩铅牡丹花的画法步骤,彩铅花卉画入门教程...
  17. 制作二十四进制的时钟特效(JavaScript)
  18. C++ include头文件之后为什么还要在编译的时候加--lxxx
  19. cleintHeight、offsetHeight、scrollHeight、cleintTop、offsetTop、scrollTop、getClientRects、getBoundingClien
  20. 一个基于java实现的代码计数器

热门文章

  1. python抓取数据时失败_python爬取页面元素失败
  2. JS提交表单的几种方式
  3. wpf title link 新窗口_新型纳米球探针:开启认知微观世界的新窗口
  4. C语言IP地址比较(IPv4/IPv6)
  5. 2022智鼎IQT测试
  6. pytorch官网教程:tensor代码理解
  7. @valid 校验_一文带你快速入手 Spring Boot 参数校验
  8. 我没捏出来的脸,淘宝帮我做到了
  9. 【5G之道】第十二章:载波聚合
  10. 将网盘的存储空间挂载到本机上 <Windows解决方案>