0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TCP编程之网卡信息获取和域名解析

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2023-06-06 11:31 次阅读

1.TCP/IP简介

TCP/IP协议源于1969年,是针对Internet开发的一种体系结构和协议标准,目的在于解决异种计算机网络通信问题。使得网络在互联时能为用户提供一种通用、一致的通信服务。是Internet采用的协议标准。

TCP/IP是一组通信协议的代名词,是由一系列协议组成的协议簇。它本身指两个协议集:

TCP(传输控制协议)。
  IP(互联网络协议)。

TCP/IP协议的基本传输单位是数据包(Datagram)。

TCP/IP传输协议,即传输控制/网络协议,也叫作网络通讯协议。它是在网络的使用中的最基本的通信协议。TCP/IP传输协议对互联网中各部分进行通信的标准和方法进行了规定。并且,TCP/IP传输协议是保证网络数据信息及时、完整传输的两个重要的协议。TCP/IP传输协议是严格来说是一个四层的体系结构,应用层、传输层、网络层和数据链路层都包含其中。

2.获取本地网卡信息

  获取本地网卡信息的方法有很多种,在Linux命令行下我们可以通过ifconfig命令查询网卡信息。

poYBAGR-oB2AR-W5AATjYDM9kL8576.png

2.1 通过ioctl函数获取网卡信息

  ioctl(input/output control)是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。

  • ioctl函数原型:
#include < sys/ioctl.h >
int ioctl(int fd, unsigned long request, ...);
形参:fd --文件描述符
      request --请求命令
      第三个参数为可变参数,该参数填写取决于request 命令;
返回值:一般成功返回0

网络相关的请求划分为6 类:

  • 接口操作
  • 文件操作
  • 接口操作
  • ARP 高速缓存操作
  • 路由表操作
  • 流系统

下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:

wKgZomR-qKKAHjq-AAIzAeIHFhc610.png

获取网卡信息示例:

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < sys/ioctl.h >
#include < net/if.h >
#include < arpa/inet.h >
#include < sys/socket.h >
#include < netinet/in.h >

int main()
{
    int i=0;
	int sockfd;
	/*创建网络套接字*/
	if((sockfd = socket(AF_INET, SOCK_STREAM,0))< 0)
	{
	    printf("socket errorn");
		return -1;
	} 
	struct ifreq ifcu_req[4];//网卡信息结构体
	struct ifconf ifc=
	{
		.ifc_len=sizeof(ifcu_req),//缓冲区大小
		.ifc_req=ifcu_req,
	};
	struct ifreq b_addr;
	int ret=ioctl(sockfd,SIOCGIFCONF, &ifc);//获取网络接口信息
	struct	sockaddr boardaddr;
	struct sockaddr_in addr;
	printf("ret=%dn",ret);
	char mac[6];
	int j=0;
	int count=ifc.ifc_len/sizeof(struct ifreq);//计算获取到的网卡信息个数
	for(i=0;i< count;i++)
	{
		printf("n------------%s---------------------n",ifcu_req[i].ifr_name);
		memcpy(&addr,&ifcu_req[i].ifr_addr,sizeof(addr));
		printf("ip地址: %s n",inet_ntoa(addr.sin_addr));
		/*广播地址*/		
		if (ioctl(sockfd, SIOCGIFBRDADDR, &ifcu_req[i]) == 0)
		{
			memcpy(&addr,&ifcu_req[i].ifr_broadaddr, sizeof(addr));
			printf("广播地址: %s n",inet_ntoa(addr.sin_addr));
		}
		/*子网掩码*/
		if (ioctl(sockfd, SIOCGIFNETMASK, &ifcu_req[i]) == 0)
		{
			memcpy(&addr,&ifcu_req[i].ifr_broadaddr, sizeof(addr));
			printf("子网掩码: %s n",inet_ntoa(addr.sin_addr));
		}
		/*MAC地址*/
		if (ioctl(sockfd, SIOCGIFHWADDR, &ifcu_req[i]) == 0)
		{
			memcpy(mac,&ifcu_req[i].ifr_hwaddr.sa_data[0],6);
			printf("mac地址:");
			for(j=0;j< 5;j++)
			{
				printf("%02X-",mac[j]);
			}
			printf("%02Xn",mac[j]);
			printf("------------------------------------n");
		}
	}
}
pYYBAGR-oKqAHSLKAAOg2PVMPHk975.png

3.域名解析

域名(英语:Domain Name),又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)。

由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串。

#include < netdb.h >
extern int h_errno;
struct hostent *gethostbyname(const char *name);
函数功能:域名解析
形参:name --域名
返回值:
struct hostent {
               char  *h_name;            /* 主机的正式名称 */
               char **h_aliases;         /* 别名列表*/
               int    h_addrtype;        /* 主机地址类型*/
               int    h_length;          /* 地址长度*/
               char **h_addr_list;       /*地址列表 */
           }
void herror(const char *s); //错误输出
const char *hstrerror(int err);//根据错误编号返回错误消息字符串

示例

#include < stdio.h >
#include < netdb.h >
#include < sys/socket.h >
#include < netinet/in.h >
#include < arpa/inet.h >
#include < string.h >
int main(int argc,char *argv[])
{
	if(argc!=2)
	{
		printf("格式:./app < 域名 >n");
		return 0;
	}
	//域名解析
	struct hostent *host_info=gethostbyname(argv[1]);
	if(host_info==NULL)
	{
		printf("err=%d,%sn",h_errno,hstrerror(h_errno));
		return 0;
	}
	int i=0;
	struct in_addr addr;
	printf("主机名:%sn",host_info->h_name);
	for(i=0;host_info->h_aliases[i]!=0;i++)
	{
		printf("主机别名:%sn",host_info->h_aliases[i]);
	}
	for(i=0;host_info->h_addr_list[i]!=0;i++)
	{
		memcpy(&addr,host_info->h_addr_list[i],sizeof(addr));
		printf("ip地址:%sn",inet_ntoa(addr));
	}
}

运行效果:

poYBAGR-p_2AWCYqAACnu8EsZlU312.png

获取邦定ip地址信息getsockname

getsockname()函数用于获取一个套接字的名字。它用于一个已捆绑或已连接套接字,本地地址将被返回。本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。

#include < sys/socket.h >
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数功能:获取sockfd绑定的ip地址和端口号信息
形  参:sockfd --网络套接字
      addr  --保存返回的ip地址和端口号信息
      addrlen --addr缓冲区大小(必须由用户设置大小,函数调用成功返回实际addr大小)
返回值:成功返回0,失败-1

示例:

#include < stdio.h >
#include < sys/types.h >          /* See NOTES */
#include < sys/socket.h >
#include < stdlib.h >
#include < unistd.h >
#include < netinet/in.h >
#include < netinet/ip.h > /* superset of previous */
#include < arpa/inet.h >
int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		printf("格式:./app < 服务器端口号 > < 服务器IP >n");
		return 0;
	}
	/*创建网络套接字*/
	int sockfd=socket(AF_INET, SOCK_STREAM,0);
	if(sockfd==-1)
	{
		printf("创建网络套接字失败n");
		return 0;
	}
	/*连接服务器*/
	struct sockaddr_in addr=
	{
		.sin_family=AF_INET,//IPV4
		.sin_port=htons(atoi(argv[1])),//服务器端口号
		.sin_addr=
		{
			.s_addr=inet_addr(argv[2]),//服务器IP
		}
	};
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)))
	{
		printf("连接服务器失败n");
		return 0;
	}
	printf("服务器连接成功n");
	struct sockaddr_in c_addr;
	socklen_t addrlen=sizeof(c_addr);
	getsockname(sockfd,(struct sockaddr *)&c_addr, &addrlen);
	printf("本地信息%s:%dn",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));
	while(1)
	{
		
	}
}
pYYBAGR-qHWAacHuAAQhmrabozM011.png
审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4982

    文章

    18281

    浏览量

    288438
  • 网卡
    +关注

    关注

    2

    文章

    285

    浏览量

    27088
  • 编程
    +关注

    关注

    88

    文章

    3440

    浏览量

    92389
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1271

    浏览量

    78291
收藏 人收藏

    评论

    相关推荐

    为什么我将一个域名解析到了服务器的Ip,但是仍然无法访问?

      有两个原因,一个原因是您的域名解析还没有生效,一般解析之后生效的时间是1-2小时。请点击开始,选择运行,然后输入 ping 您的域名地址,比如 ping www.abc.com
    发表于 11-22 00:38

    [讨论]域名解析了,网站却打不开的原因

    域名解析了,网站却打不开的原因 有两个原因,一个原因是您的域名解析还没有生效,一般解析之后生效的时间是1-2小时。请点击开始,选择运行,然后输入 ping 您的域名地址,比如 ping
    发表于 11-25 18:54

    双线双IP(多线多IP)域名智能解析教程

    域名DNS的地方即可) 3、选择 “填写具体信息”。也就是修改为第三方的DNS解析服务器。dnspod最新的免费DNS为f1g1ns1.dnspod.net
    发表于 04-18 13:44

    华为mu509支持域名解析吗?

    最近调试3G模块,mu203说明书里AT指令没DNS域名解析介绍,请问哪位大侠知道它到底支不支持域名解析?还有mu509支持吗?
    发表于 07-12 10:07

    mu203有域名解析功能吗?

    内容最近调试3G模块,mu203说明书里AT指令没DNS域名解析介绍,请问哪位大侠知道它到底支不支持域名解析?谢谢
    发表于 07-12 10:10

    【BPI-M64试用体验】如何判断网络是否公网ip及动态域名解析介绍

    谅。------------------------------------------------------------------------------------------公网ip是全球唯一的,所以你要想在家外访问到家中的计算机,在不用域名解析的情况下就要求你要有公网ip。内网ip是经过网络地址转换(N
    发表于 06-21 01:10

    如何解决DNS解析错误故障

    没有办法的时候在用)小知识:每个windows系统都有个HOSTS文件,它的作用是加快域名解析,方便局域网用户,屏蔽网站,顺利连接系统等功能。3:清除DNS缓存信息的方法“开始->运行->
    发表于 09-29 15:14

    使用JavaScript代码在Rapid板子上实现DNS解析域名得到IP地址操作分享!

    ,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。在这里,您将了解到如何使用JavaScript代码在Rapid板子上来实现DNS解析域名得到IP地址。Javascr
    发表于 08-15 04:17

    没有操作系统真的不能使用LwIP套接字和域名解析吗?

    裸机移植了LwIP协议栈,整体感觉不错但是在使用套接字(Socket)功能和域名解析(lwip_gethostbyname)时发现编译通不过,说是要启用操作系统。如果不用操作系统就只能用RAW
    发表于 08-22 22:25

    关于DDNS动态域名的描述

    上网得到新的动态分配的IP地址之后,程序就会把这个IP地址发送到动态域名解析服务器,更新域名解析数据库。Internet上的其他人要访问这个域名的时候,动态域名解析服务器会返回正确的I
    发表于 05-30 17:42

    esp32连接手机热点无法解析域名是什么原因?

    版本:idf3.3.3硬件:esp32-worver-e esp32连接手机热点后(红米 note9 pro)成功后。无法进行域名解析。直接使用IP可以进行连接。esp32 连接笔记本热点,无线路由器等能正常使用域名连接。这个是什么原因?是手机热点没有
    发表于 02-16 07:24

    动态域名解析、E-mail的工作原理

    阐述动态域名解析、E-mail 工作原理,重点介绍SMTP 及安全认证,在linux 下用动态域名解析与Sendmail+SASL 构建安全、经济而实用的动态邮件服务器。为中小企业、部门架建小型服务器提
    发表于 08-06 08:59 35次下载

    汉邦高科域名解析教程

    汉邦高科域名解析教程
    发表于 01-04 14:22 0次下载

    汉邦高科域名解析设置说明

    汉邦高科域名解析设置说明
    发表于 01-04 14:34 0次下载

    域名解析是什么意思?

    域名解析是互联网基础设施中至关重要的一部分。 域名解析包括两个主要的步骤: 1、域名查询:当我们在浏览器中输入一个域名(例如,www.hengxun.cn),我们的计算机首先需要查询
    的头像 发表于 11-21 17:36 1023次阅读