7.物联网LWIP之DNS,超时机制,组播,广播

这篇具有很好参考价值的文章主要介绍了7.物联网LWIP之DNS,超时机制,组播,广播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一。DNS域名解析

1.DNS作用

      DNS是计算机域名系统(Domain Name System 或 Domain Name Service)的缩写,它是由解析器和域名服务器组成的,作用是把域名转换成为网络可以识别的ip地址。举一个简单的例子,域名相当于门牌号,而IP地址相当于具体的地理位置。

      DNS是用来做域名解析的,它会在你上网输入网址后,把它转换成IP,然后去访问对方服务器,没有它,如果想上百度就要记住百度的IP,上163就要记住163的IP,有了DNS的处理,你只需要记住对应的域名也就是网址就可以了。

2.DNS API

(1)宏开关

需要使用DNS,所以需要把这个宏开关打开,原因:本来就是这样设定

//opt.h
/**
 * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
 * transport.
 */

#if !defined LWIP_DNS || defined __DOXYGEN__
#define LWIP_DNS                        1
#endif

在LWIP的文件夹中

7.物联网LWIP之DNS,超时机制,组播,广播,物联网(2)配置DNS服务器

<1>dns.c添加代码

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

//dns.c 需要手动添加
/** DNS server IP address */
#ifndef DNS_SERVER_ADDRESS
extern ip4_addr_t gw;   //网关地址
#define DNS_SERVER_ADDRESS(ipaddr)        (memcpy(ipaddr, &gw, sizeof(ip4_addr_t)))
#endif

#ifdef DNS_SERVER_ADDRESS
  /* initialize default DNS server address */
  ip_addr_t dnsserver;
  DNS_SERVER_ADDRESS(&dnsserver);
  dns_setserver(0, &dnsserver);
#endif /* DNS_SERVER_ADDRESS */

<2>lwip.c修改代码

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

<3>gethostbyname

//netdb.h
/** @ingroup netdbapi */
#define gethostbyname(name) lwip_gethostbyname(name)
struct hostent *lwip_gethostbyname(const char *name);
struct hostent {
    char  *h_name;      /* 正式主机名 */
    char **h_aliases;   /* 主机别名*/
    int    h_addrtype;  /* 主机IP地址类型 */
    int    h_length;    /* 主机IP地址字节长度*/
    char **h_addr_list; /* 主机的IP地址列表*/
};

DNS获取到的内容为一个结构体,最主要的是最后一项(主机的ip地址列表)

3.实验:实现DNS解析

(1)dns_client.h

#ifndef _DNS_CLIENT_H
#define _DNS_CLIENT_H

void vDnsClientTask(void);

#endif

(2)dns_client.c

#include "socket_tcp_server.h"
#include "dns_client.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "FreeRTOS.h"
#include "task.h"
#include "netdb.h"

static char ReadBuff[BUFF_SIZE];

void vDnsClientTask(void){

	int 	 cfd, n, i, ret;
	struct sockaddr_in server_addr;
	//dns 域名解析功能
	struct hostent *p_hostent = NULL;
	
	p_hostent = gethostbyname("www.makeru.com.cn");
	if(p_hostent){
		for(i = 0; p_hostent->h_addr_list[i]; i++){		
			printf("host ip:%s\r\n", inet_ntoa(*p_hostent->h_addr_list[i]));				
		}
		
	}else{	
		printf("get host ip fail!\r\n");
	}
		
again:	
	//创建socket
	cfd = Socket(AF_INET, SOCK_STREAM, 0);
	
	server_addr.sin_family 			= AF_INET;
	server_addr.sin_port   			= htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
	//连接到服务器
	//connect 其实是一个阻塞接口,内部要完成TCP的三次握手,当然有超时机制,所以我们需要等一段时间,才能重新连接到服务器
	ret = Connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(ret < 0){
		//100ms去连接一次服务器
		vTaskDelay(100);
		goto again;
	
	}
	
	printf("server is connect ok\r\n");
	
	while(1){
		//等待服务器发送数据
		n = Read(cfd, ReadBuff, BUFF_SIZE);
		if(n <= 0){
		
			goto again;
		
		}
		//进行大小写转换
		for(i = 0; i < n; i++){
		
			ReadBuff[i] = toupper(ReadBuff[i]);		
		}
		//写回服务器
		n = Write(cfd, ReadBuff, n);
		if(n <= 0){
		
			goto again;
		
		}		
	}
}

二。心跳及超时机制实现

1.心跳检测

网线掉了怎么办?

    心跳检测就是应对网络断开出现的没有报错的问题,以前优化stm32作为服务器端的代码时,仅仅只是对客户端连接失败做出了错误提示,但是在网络断开的时候,是不会有任何反应的。

2.setsocketopt

//功能说明:  
/*
获取或者与某个套接字关联的选 项。选项可能存在于多层中,它们总会出现在最上面的套接字层。当操作套接字选项时,选项位于的层和选项的名称必须给出。为了操作套接字层的选项,应该 将层的值指定为SOL_SOCKET。为了操作其它层的选项,控制选项的合适协议号必须给出。例如,为了表示一个选项由协议解析,层应该设定为协议 号TCP。
*/
//函数原型
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
//参数:  
/*
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。
*/
//返回说明:  
成功执行时,返回0。失败返回-1
    
//参数详细说明:
/*
level指定控制套接字的层次.可以取三种值:
1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP选项.
3)IPPROTO_TCP:TCP选项. 

选项名称        说明                     数据类型
=====================================================================
            SOL_SOCKET
---------------------------------------------------------------------
SO_BROADCAST      允许发送广播数据            int
SO_DEBUG        允许调试                int
SO_DONTROUTE      不查找                   int
SO_ERROR        获得套接字错误             int
SO_KEEPALIVE      保持连接                int
SO_LINGER        延迟关闭连接              struct linger
SO_OOBINLINE      带外数据放入正常数据流         int
SO_RCVBUF        接收缓冲区大小             int
SO_SNDBUF        发送缓冲区大小             int
SO_RCVLOWAT       接收缓冲区下限             int
SO_SNDLOWAT       发送缓冲区下限             int
SO_RCVTIMEO       接收超时                struct timeval
SO_SNDTIMEO       发送超时                struct timeval
SO_REUSERADDR      允许重用本地地址和端口        int
SO_TYPE         获得套接字类型               int
SO_BSDCOMPAT      与BSD系统兼容            int
========================================================================
            IPPROTO_IP
------------------------------------------------------------------------
IP_HDRINCL       在数据包中包含IP首部          int
IP_OPTINOS       IP首部选项               int
IP_TOS         类型
IP_TTL         生存时间                  int
========================================================================
            IPPROTO_IP
------------------------------------------------------------------------
TCP_MAXSEG       TCP最大数据段的大小           int
TCP_NODELAY       不使用Nagle算法               int
=====================================================================


*/

3.TCP Keepalive

(1)setsockopt参数

<br class="Apple-interchange-newline"><div></div>

#define SO_KEEPALIVE   0x0008  /* 保持连接 */                   val = int
#define TCP_KEEPIDLE   0x03    /* 发送心跳空闲周期 S*/           val = int
#define TCP_KEEPINTVL  0x04    /* 发送心跳间隔 S */              val = int
#define TCP_KEEPCNT    0x05    /* 心跳重发次数 */                val = int

(2)宏开关

/**
 * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
 * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
 * in seconds. (does not require sockets.c, and will affect tcp.c)
 */
#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__
#define LWIP_TCP_KEEPALIVE              0
#endif

4.实验:心跳检测

步骤:

(1)opt中keepalive开启

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

 (2)tcp_keepalive.h

#ifndef _TCP_KEEPALIVE_H
#define _TCP_KEEPALIVE_H

void vTcpKeepaliveTask(void);
#endif

(3)tcp_keepalive.c

#include "socket_tcp_server.h"
#include "tcp_keepalive.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "FreeRTOS.h"
#include "task.h"

static char ReadBuff[BUFF_SIZE];


void vTcpKeepaliveTask(void)
{

	int 	 cfd, n, i, ret;
	struct sockaddr_in server_addr;
	
	int 	so_keepalive_val = 		1;
	int 	tcp_keepalive_idle = 	3;
	int   tcp_keepalive_intvl = 3;
	int		tcp_keepalive_cnt = 	3;
	int		tcp_nodelay = 1;
again:	
	//创建socket
	cfd = Socket(AF_INET, SOCK_STREAM, 0);
	//使能socket层 心跳检测
	setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive_val, sizeof(int));
	
	server_addr.sin_family 			= AF_INET;
	server_addr.sin_port   			= htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
	//连接到服务器
	//connect 其实是一个阻塞接口,内部要完成TCP的三次握手,当然有超时机制,所以我们需要等一段时间,才能重新连接到服务器
	ret = Connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(ret < 0){
		//100ms去连接一次服务器
		vTaskDelay(100);
		goto again;
	
	}
	
	//配置心跳检测参数   默认参数时间很长
	setsockopt(cfd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepalive_idle, sizeof(int));	
	setsockopt(cfd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepalive_intvl, sizeof(int));	
	setsockopt(cfd, IPPROTO_TCP, TCP_KEEPCNT, &tcp_keepalive_cnt, sizeof(int));	
	setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, sizeof(int));	
	
	
	printf("server is connect ok\r\n");
	
	while(1){
		//等待服务器发送数据
		n = Read(cfd, ReadBuff, BUFF_SIZE);
		if(n <= 0){
		
			goto again;
		
		}
		//进行大小写转换
		for(i = 0; i < n; i++){
		
			ReadBuff[i] = toupper(ReadBuff[i]);		
		}
		//写回服务器
		n = Write(cfd, ReadBuff, n);
		if(n <= 0){
		
			goto again;
		
		}		
	}
}

三。组播与广播基础知识

1.组播,广播区分

2.广播实现

注意必须使能项

#if !defined LWIP_IGMP || defined __DOXYGEN__
#define LWIP_IGMP                       1
#endif

(1)广播实现

//SOL_SOCKET
#define SO_BROADCAST   0x0020 /* 广播许可 */                
//val = int

(2)组播实现

//IPPROTO_IP
#define IP_ADD_MEMBERSHIP  3    /*加入组播*/
#define IP_DROP_MEMBERSHIP 4    /*退出组播*/
#define IP_MULTICAST_IF    6    /*组播默认网卡选择*/
#define IP_MULTICAST_LOOP  7    /*组播默认回环*/

//val
typedef struct ip_mreq {
    struct in_addr imr_multiaddr; /* IP multicast address of group */
    struct in_addr imr_interface; /* local IP address of interface */
} ip_mreq;

(1)boradcast.h

#ifndef _BORADCAST_H
#define _BORADCAST_H

void vBoradcastTask(void);
#endif

(2)boradcast.c

#include "boradcast.h"
#include "socket_tcp_server.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "string.h"
#include "FreeRTOS.h"
#include "task.h"

/**
  * @brief  boradcast 服务器任务
  * @param  None
  * @retval None
  */
void vBoradcastTask(void){

	int 	 sfd;
	struct sockaddr_in client_addr;
	socklen_t	client_addr_len;
	int optval = 1;	
	//创建socket	udp通信
	sfd = Socket(AF_INET, SOCK_DGRAM, 0);
	
	setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
	client_addr.sin_family			= AF_INET;
	client_addr.sin_port				= htons(SERVER_PORT);
	client_addr.sin_addr.s_addr	= inet_addr("255.255.255.255");
	client_addr_len = sizeof(client_addr);
	while(1){
		//发送广播数据
		Sendto(sfd, "broadcast data", strlen("broadcast data"), 0, (struct sockaddr *)&client_addr, client_addr_len);
		vTaskDelay(5000);
	}
	
}

4.组播实现:

配置:

使能IPv4的muticast

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

(1)multicast.h

#ifndef _MULTICAST_H
#define _MULTICAST_H
void vMulticastTask(void);

#endif

(2)multicast.c

#include "multicast.h"
#include "socket_tcp_server.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "string.h"
#include "FreeRTOS.h"
#include "task.h"
#include "sockets.h"

/**
  * @brief  multicast 服务器任务
  * @param  None
  * @retval None
  */ 
void vMulticastTask(void){

	int 	 sfd;
	struct sockaddr_in client_addr;
	socklen_t	client_addr_len;	
	struct ip_mreq multicast_mreq;
	//填充组播地址信息
	multicast_mreq.imr_multiaddr.s_addr = inet_addr("224.0.1.1");
	multicast_mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	//创建socket	udp通信
	sfd = Socket(AF_INET, SOCK_DGRAM, 0);
	//设置组播选项
	setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_IF, &multicast_mreq, sizeof(multicast_mreq));
	
	
	client_addr.sin_family			= AF_INET;
	client_addr.sin_port				= htons(SERVER_PORT);
	client_addr.sin_addr.s_addr	= inet_addr("224.0.1.1");	//组播ip
	client_addr_len = sizeof(client_addr);
	while(1){
		//发送广播数据
		Sendto(sfd, "multicast data", strlen("multicast data"), 0, (struct sockaddr *)&client_addr, client_addr_len);
		vTaskDelay(5000);
	}
	
}

四。wireshark抓包验证

补充:wireshark的常用按键

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

1.wireshark使用

(1)使用流程

        选择网卡---》过滤配置

(2)过滤器使用方法

<1>比较运算符

    eq, ==    Equal
    ne, !=    Not Equal
    gt, >     Greater Than
    lt, <     Less Than
    ge, >=    Greater than or Equal to
    le, <=    Less than or Equal to

<2>协议字段

#以太网过滤
eth.dst eq ff:ff:ff:ff:ff:ff
#IP地址过滤
ip.dst eq 192.168.1.10
ip.src == 192.168.1.1
#TCP过滤
tcp.port == 6666
# UDP过滤
udp.port == 6666
# http过滤
http.request.method == "POST"

<3>位域操作

# TCP SYN
tcp.flags & 0x02

<4>逻辑表达式

    and, &&   Logical AND
    or,  ||   Logical OR
    not, !    Logical NOT
   # tcp.port == 80 and ip.src == 192.168.2.1

 2.结果(在上述广播实验的基础上,在抓包工具中检测)

(1)这是广播的抓包

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

7.物联网LWIP之DNS,超时机制,组播,广播,物联网

 (2)这是组播的抓包文章来源地址https://www.toymoban.com/news/detail-662651.html

到了这里,关于7.物联网LWIP之DNS,超时机制,组播,广播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 广播、组播

    向子网中多台计算机发送消息,并且子网中所有的计算机都可以接收到发送方发送的消息,每个广播消息都包含一个特殊的IP地址,这个IP中子网内主机标志部分的二进制全部为1。 a.只能在局域网中使用。 b.客户端需要绑定服务器广播使用的端口,才可以接收到广播消息。 单

    2024年02月11日
    浏览(25)
  • udp多点通信-广播-组播

    单播 每次只有两个实体相互通信,发送端和接收端都是唯一确定的。 主机之间的一对多的通信 所有的主机都可以接收到广播消息(不管你是否需要) 广播禁止穿过路由器(只能做局域网通信) 只有UDP可以广播 广播地址 有效网络号+全是1的主机号 192.168.50.123 -----》 192.168.5

    2024年02月05日
    浏览(28)
  • 计算机网络 | 广播与组播

    欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。 专栏:《Linux从小白到大神》《网络编程》 首先

    2024年02月05日
    浏览(26)
  • 网络编程(三)—— UDP(单播、广播、组播)

    UDP协议的特点: 无连接 、不保证传输可靠(可能重复到达、失序、丢失、无字节流控制(数据传输快的会淹没慢的)) UDP传输 UDP 服务端(接收端)的搭建流程 UDP客户端(发送端)的搭建流程 通信流程 sendto 和 recvfrom 这两个函数一般在使用UDP协议时使用 sendto recvfrom 单播就

    2024年02月04日
    浏览(25)
  • Java UDP通信详解:单播、广播、组播

    1.UDP是一种无连接、不可靠传输的协议; 2.将数据源IP、目的地IP和端口封装成数据包,不需要建立连接 ; 3.每个数据包的大小限制在64KB内; 4.发送不管对方是否准备好,接收方收到也不确认,故是不可靠的; 5.可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快

    2024年02月02日
    浏览(37)
  • 2.物联网LWIP网络

    注意:学习路径 1.如果想要深入了解,学习LWIP的ARM API(对底层操作) 2.如果想要快速开发,学习LWIP的Socket API(针对操作系统) 一。LWIP协议栈 (1)LWIP应用场景          上述是以太网DTU,通过这个器件可以很快捷的把数据传递到以太网上,即DTU就是硬件与以太网传递的中

    2024年02月13日
    浏览(24)
  • 11.物联网lwip,网卡原理

    一。LWIP协议栈内存管理 1.LWIP内存管理方案 (1)堆heap 1.灰色为已使用内存 2.黑色为未使用内存 3.紫色为使用后内存 按照某种算法,把数据放在内存块中 (2)池pool 设置内存池,设置成大小相同的内存块。  2.LWIP内存管理 (1)内存池API //内存池初始化 void  memp_init(void); //内

    2024年02月10日
    浏览(22)
  • 组播路由协议——PIM SM工作机制

    目录 PIM SM基本概念 PIM工作步骤 DR竞选 RP基本概念(Bootstrap自举报文) RP的作用 RP的两种类型 RP的缺点 PIM SM建树过程 成员接收者到RP建树过程(Join加入报文) 组播源到RP建树过程(Register注册报文、Join加入报文) SPT切换 SSM模型 PIM SM采用“拉”(Pull)的方式来转发组播报文

    2024年02月07日
    浏览(28)
  • 10.物联网LWIP之TCP状态转变

    一。TCP状态机 1.青粗线:理想TCP状态转变(服务器视角下) 2.虚线:被动TCP状态转变(服务器视角下) 3.细实线:不经常出现的TCP状态转变(类似于边界处理) 1.青粗线解释--》服务器主动通信,客户端被动通信(服务器也可作为客户端) (1)服务器主动创建socket后开始监听

    2024年02月10日
    浏览(26)
  • 1.物联网LWIP网络,TCP/IP协议簇

    一。TCP/IP协议簇 1.应用层:FTP,HTTP,Telent,DNS,RIP 2.传输层:TCP,UDP 3.网络层:IPV4,IPV6,OSPF,EIGRP 4.数据链路层:Ethernet,FrameRelay,Is-Is 注意:IWIP是完全按照TCP/IP协议来创建 2.OSI七层模型与TCP/IP协议模型 3.通讯过程 应用层:FTP协议 传输层:TCP协议 网络层:IP协议 链路层:

    2024年02月11日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包