局域网内查询嵌入式设备IP的几种方式

前言

最近有个需求,所有本地海思的板子,都要能查询到他们的IP。如果是用串口调试,当然很容易知道IP,但是大部分情况下,我们还是用telnet远程连接,这时候,不知道IP就啥也干不了。

因此我想着在海思的板子上跑一个服务器程序,然后在本地运行客户端程序去查询,服务器接收到数据就将自己的IP返回给客户端,这样就知道所有海思芯片的IP了。

一开始是做了一个用TCP协议通信的,但是考虑到ABC三类IP加起来数量太多了,线程开太多,程序会把电脑卡死。然后又尝试了UDP广播,但是又不能做到跨网段,最终的解决方案是不使用C-S方式(客户端-服务器),而是采用对等连接方式P2P(peer to peer),在通信的时候,并不区分是服务器还是客户端,而是两台主机同时具有服务器和客户端的能力。并且发送信息的方式,都是往255.255.255.255广播,这样就能跨网段进行接收了。

本文档将所有码记录下来,并对关键点进行解释,方便以后查阅。

windows端所使用的线程API,是一个朋友封装的,文档中不提供代码,但是下载资源中可以找到

本文档资源地址:https://download.csdn.net/download/whitefish520/12831608

TCP方式

服务器

服务器端监听所有IP,并在客户端接入后,创建线程,发送自己的IP

//linux arm-hisiv500-linux-gcc server.c -o server -lpthread    

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include<ctype.h>
#include<stdlib.h>
#include<pthread.h>

void *run(void *arg);
void trim(char *strIn, char *strOut);

int main(){
   
		//lfd:socket返回的文件描述符,用lfd监听并接受客户端连接
   		//cfd:客户端链接上来返回的cfd,用cfd和客户端通信
        int lfd,cfd;
        int opt = 1;
		char client_ip[256];
        //serv_addr服务器地址
        //client_addr客户端地址
        struct sockaddr_in serv_addr,client_addr;
        socklen_t client_len;
        pthread_t tid;	
        
        //socket创建服务器返回lfd文件描述符
        lfd = socket(AF_INET,SOCK_STREAM,0);
        setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        bzero(&serv_addr,sizeof(serv_addr));
        //ipv4
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(8080);
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   
        //bind
        bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
        //监听是否有客户连接
        listen(lfd,256);
       
        while(1){
   
           client_len = sizeof(client_addr);//客户端地址长度
           //连接成功返回cfd,用cfd和客户通信
           cfd = accept(lfd,(struct sockaddr*)&client_addr,&client_len);
		   printf("client:%s\t%d\n",
               inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip,sizeof(client_ip)),
		       ntohs(client_addr.sin_port));
		   //创建线程 回调 run方法  cfd做参数传入 
           pthread_create(&tid,NULL,run,(void *)cfd);  
           pthread_detach(tid);
		}
		return 0;
} 
void *run(void *arg){
   
	int cfd = (int ) arg;
	char buf[1024];//缓冲区
	char ipbuf[1024];//缓冲区
	int len,i;
	char *pinfo;
    FILE *fp;
    
	while(1){
   
		system("ifconfig -a | grep 'inet addr' > ipinfo");	//获取ip并写入文件
        fp = fopen("ipinfo", "r");
		if (fp == NULL)
		{
   
			printf("fopen error!\n");
			return;
		}
		while (!feof(fp)) 
      	{
    
			fgets(buf,1024,fp);  //从文件中一行一行读出数据
			if(!feof(fp)) {
   
				trim(buf, ipbuf);	//取出首尾的空格
				write(cfd,ipbuf,strlen(ipbuf));//发送给服务器
			}
      	} 
		fclose(fp);	
		system("rm ipinfo");	//发送完毕,删除ip信息文件
		break;
	}
	close(cfd);
}

//实现去除首尾空格的效果
void trim(char *strIn, char *strOut)
{
   
    int i, j ;
    i = 0;
    j = strlen(strIn) - 1;
    while(strIn[i] == ' ')
        ++i;
    while(strIn[j] == ' ')
        --j;
    strncpy(strOut, strIn + i , j - i + 1);
    strOut[j - i + 1] = '\0';
}

客户端

客户端程序做了对Windows的适配,需要Windows上安装MinGW gcc编译器,编译命令在注释中

客户端要求执行时输入一个参数,例如./client 192.168.10,注意只要三段,客户端会对1-255尝试连接,成功则创建线程,打印信息

//win32  gcc client.c pps_thread_win32.c -o client.exe  -lwsock32
//linux  gcc client.c -o client -lpthread   

#ifdef _WIN32
	#include <stdio.h>
	#include <winsock2.h>
	#include "pps_thread.h"
	#pragma comment(lib,"ws2_32.lib")
#else
	#include<stdio.h>
	#include<stdlib.h>
	#include<errno.h>
	#include<string.h>
	#include<sys/types.h>
	#include<netinet/in.h>
	#include<sys/socket.h>
	#include<sys/wait.h> 
#endif

#define DEST_PORT 8080//目标地址端口号 
#define MAX_DATA 100//接收到的数据最大程度 

char targetIP[32];
int stop = 0;
 
void *run(void *arg)
{
   
#ifdef _WIN32
	SOCKET sockfd;
	WSADATA wsaData;
	WORD w
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值