最新要闻
- 天天热讯:巨轮智能:公司近期经营情况正常 内外部经营环境未发生重大变化
- 美国《国家地理》回应传闻:不会停刊、不影响内容质量
- 新西兰升级禁塑令:违者将被罚款44万元 世界速递
- 中外合作办学 授予中、英学士学位 凯里学院这个专业计划招生120人
- 终结日本队5连冠!中国女篮时隔12年再得亚洲杯冠军
- 惠普发布新款游戏显示器:2K IPS屏、240Hz高刷|播资讯
- 全球简讯:泰州市召开“泰惠农•金融服务乡村振兴”农业农村重大项目专题对接会
- 【全球新视野】问界M5智驾版发布全新OTA升级 加入全新智驾领航辅助等功能
- 真世界霸主!任天堂第一方收入远超索尼、微软
- 6月北京口岸出入境人员突破88万,再创今年出入境流量新高 全球观点
- 特斯拉将采用线控转向技术 Yoke方向盘能否全面普及? 环球要闻
- 20万买“小奔驰”图什么?
- 卷疯了!全新马自达3昂克赛拉正式上市 9.99万到底值不值?_观点
- 中非经贸博览会指定用车,岚图梦想家到底哪里好? 焦点热议
- AMD食言了!说好的显卡性能神技HYPR-RX跳票
- 至高优惠200元 华为MatePad Air 原野绿新色上市开启预售 天天快资讯
手机
光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
- 搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 视点!美国首位女总统即将诞生?拜登恐怕要提前下岗,美政坛迎来变局?
- 当前速递!用理想仪器实现更好的颗粒 德国新帕泰克亮相CPHI & PMEC China获好评
- 微粒贷怎么申请开通 开通方法如下
- 焦点简讯:心疼!这位40岁的云南缉毒警,已是满头白发
家电
LinuxDNS分析从入门到放弃(记一次有趣的dns问题排查记录,ping 源码分析,getaddrinfo源码分析)
PS:要转载请注明出处,本人版权所有。PS: 这个只是基于《我自己》的理解,如果和你的原则及想法相冲突,请谅解,勿喷。
环境说明
ubuntu 18.04
(资料图)
前言
我们这里有一块嵌入式板卡,当我们通过PING测试内网IP时,发现外网IP访问正常,但是测试域名访问一直报unknown host。一般来说,在ubuntu里面,我们遇到域名不能访问,反手就是去设置/etc/resolv.conf文件里面的nameserver为114.114.114.114。但是万万没有想到,这次我们这样改了之后,还是访问报unknown host。
当时我就人麻了,但是我仿佛灵光一闪,想到了一个问题:为何以前我们修改了/etc/resolv.conf文件就DNS就正常了,但是这里同样修改了这个文件,就不正常工作?此外,/etc/resolv.conf文件是干嘛的,为何改了DNS就有效了?
要回答以上问题,根本原因就是要了解Linux平台里面DNS的详细工作流程,于是我踏上了看源码之旅。
探索之旅
在这里,我们第一件事情就是想到,当我们ping一个域名,或者我们在浏览器里面输入了一个域名,然后访问的那一刻发生了什么?
首先,当我们进行网络编程的时候,我们不管是send udp msg还是send tcp msg,我们都是需要构建一个struct sockaddr结构,这个结构里面包含了访问的地址,端口等等信息。但是这里的地址是ip地址,并不是域名地址,因此可以猜测,在浏览器访问或者ping域名之前,肯定做了dns查询工作,然后将域名转换之后,得到ip地址才构建出struct sockaddr结构,然后才开始网络访问的操作的。
下面我去翻阅了ping的源码,在https://git.savannah.gnu.org/cgit/inetutils.git/tree/ping/libping.c?h=v2.4 中的ping_set_dest 函数中,有一个将host转换为struct sockaddr的方法引起了我的注意,他就是:getaddrinfo / gethostbyname。下面是ping的简要工作流程:
- 在https://git.savannah.gnu.org/cgit/inetutils.git/tree/ping/ping.c?h=v2.4中,main函数中调用了argp_parse,这里面会调用parse_opt,在这里有一个重要的ping_type函数指针在这里设置了,如果我们不配置任何参数的话,那么就是调用的ping_echo函数。
- 在https://git.savannah.gnu.org/cgit/inetutils.git/tree/ping/ping.c?h=v2.4中,main函数中调用了ping_init,初始化了ICMP的socket,并记录到句柄PING中。
- 在经历各种初始化后,就会调用ping_type,后面我们默认分析ping_echo。
- 在https://git.savannah.gnu.org/cgit/inetutils.git/tree/ping/ping_echo.c?h=v2.4中,ping_echo中回去调用ping_set_dest设置参数,同时调用ping_run循环通过send_to发送ping icmp报文。
- 在https://git.savannah.gnu.org/cgit/inetutils.git/tree/ping/libping.c?h=v2.4中,ping_set_dest 调用getaddrinfo解析域名。
getaddrinfo / gethostbyname
首先,我们在查这两个方法之前,可以猜测他们的一个功能就是:这两个函数可能拿着域名,去访问了域名服务器,然后解析出ip地址,并且构造了struct sockaddr结构并返回。
因此我们去看看这两个函数相关的man介绍和源码:根据man手册:https://man7.org/linux/man-pages/man3/getaddrinfo.3.html ,我们可以知道,getaddrinfo已经包含了gethostbyname的工作,因此我们就只需要分析这个方法就行。
getaddrinfo 参数分析
我们先来看看这个函数的参数含义
//重要的参数结构体struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next;};int getaddrinfo (const char *name, const char *service, const struct addrinfo *hints, struct addrinfo **pai);//根据https://man7.org/linux/man-pages/man3/getaddrinfo.3.html,我们可以知道://name: 域名//service: 服务,注意这里这个服务会让我们重新复习一遍计算机网络。//hints: 就是填写struct addrinfo里面的属性,然后getaddrinfo根据这些特殊指定的属性,将对应的struct addrinfo返回回来。//pai: 此函数返回的一个链表,其中包含了符合要求的struct addrinfo信息。//其实我们从pai可以知道,当返回有值时,意味着我们知道了一个域名和服务对应的网络地址,然后我们就可以在connect,bind中使用pai->ai_addr了。
getaddrinfo 例子调试分析
注意:我这里是事后写本文的时候,才发现需要下面的内容。由于getaddrinfo的实现特殊性,其不是很方便查看源码,因此采取strace + gdb + simple example方式来分析此函数的实现。
首先下面是我的simple example
#include #include #include #include #include #include #include #include int main(int argc, char * argv[]){struct addrinfo hints, *res; memset (&hints, 0, sizeof (hints)); hints.ai_family = AF_INET; hints.ai_flags = AI_CANONNAME;if (0 > getaddrinfo("baidu.com", NULL, &hints, &res)){perror("get error:");return -1;}struct sockaddr_in * get_addr = res->ai_addr;printf("ip for baidu: %s\n", inet_ntoa(get_addr->sin_addr));return 0;}
然后gcc test.c -o test -g 生成此执行文件。下面是执行此函数的结果图片:
下面是一些读取源码需要的单词简写:
- IDNA: Internationalizing Domain Names in Applications
- NSCD: name service cache daemon
- NSS: Name Services Switch
- CNAME: canonical name (规范化名字)
下面是resolv.conf的文件内容:
# resolve.conf 内容# This file is managed by man:systemd-resolved(8). Do not edit.## This is a dynamic resolv.conf file for connecting local clients to the# internal DNS stub resolver of systemd-resolved. This file lists all# configured search domains.## Run "systemd-resolve --status" to see details about the uplink DNS servers# currently in use.## Third party programs must not access this file directly, but only through the# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,# replace this symlink by a static file or a different symlink.## See man:systemd-resolved.service(8) for details about the supported modes of# operation for /etc/resolv.conf.# nameserver 127.0.0.53nameserver 8.8.8.8options edns0
下面是strace ./test 输出的部分节选(包含了/etc/resolv.conf的内容)
//打开resolve.confopenat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3fstat(3, {st_mode=S_IFREG|0644, st_size=736, ...}) = 0read(3, "# This file is managed by man:sy"..., 4096) = 736read(3, "", 4096) = 0close(3)//通过resolve.conf的dns服务器,查询dns//这里有个小知识:dns服务器的默认端口是53,详细可以通过/etc/protocol,/etc/services查看socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = 0poll([{fd=3, events=POLLOUT}], 1, 0) = 1 ([{fd=3, revents=POLLOUT}])sendto(3, "5\244\1\0\0\1\0\0\0\0\0\1\5baidu\3com\0\0\1\0\1\0\0)\4\260"..., 38, MSG_NOSIGNAL, NULL, 0) = 38poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])ioctl(3, FIONREAD, [70]) = 0recvfrom(3, "5\244\201\200\0\1\0\2\0\0\0\1\5baidu\3com\0\0\1\0\1\300\f\0\1\0"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [28->16]) = 70close(3) = 0
首先我们要调试glibc的话,需要安装glibc的调试符号:
sudo apt-get install libc6-dbgcd /usr/src/glibctar -xf glibc-{version}.tar.xz
下面通过GDB 结合 GLIBC的debug info开始调试程序,分析出getaddrinfo中我想关注的部分。
首先我们调试得到打开/etc/resolv.conf的实现:
gdb ./testb fopen# 设置gdb搜索源文件目录,注意你下断点时,对应源码的相对路径(gdb) set directories /usr/src/glibc/glibc-2.27/xxxx
在多次运行后,抓到打开/etc/resolv.conf的地方,其堆栈如下:
#0 _IO_new_fopen (filename=filename@entry=0x7ffff7b98cea "/etc/resolv.conf", mode=mode@entry=0x7ffff7b9578c "rce") at iofopen.c:88#1 0x00007ffff7b25c0f in __resolv_conf_load (preinit=preinit@entry=0x0) at res_init.c:553#2 0x00007ffff7b28459 in __resolv_conf_get_current () at resolv_conf.c:162#3 0x00007ffff7b26cad in __res_vinit (statp=0x7ffff7dd1bc0 <_res>, preinit=preinit@entry=0) at res_init.c:609#4 0x00007ffff7b27e50 in maybe_init (preinit=false, ctx=0x555555756530) at resolv_context.c:122#5 context_get (preinit=false) at resolv_context.c:184#6 __GI___resolv_context_get () at resolv_context.c:195#7 0x00007ffff7ae790e in gaih_inet (name=name@entry=0x555555554924 "baidu.com", service=, req=req@entry=0x7fffffffdeb0, pai=pai@entry=0x7fffffffd9c8, naddrs=naddrs@entry=0x7fffffffd9c4, tmpbuf=tmpbuf@entry=0x7fffffffda30) at ../sysdeps/posix/getaddrinfo.c:767#8 0x00007ffff7ae9c84 in __GI_getaddrinfo (name=, service=, hints=0x7fffffffdeb0, pai=0x7fffffffdea0) at ../sysdeps/posix/getaddrinfo.c:2300#9 0x000055555555483b in main (argc=1, argv=0x7fffffffdfd8) at test.c:17
因此我们得到了getaddrinfo的打开resolv.conf的调用路径,其值如下:getaddrinfo-->gaih_inet->__resolv_context_get()->context_get()->maybe_init()->__res_vinit()->__resolv_conf_get_current()->__resolv_conf_load() 这里面会打开resolv.conf
注意,当真正的打开了resolv.conf后,其还会解析此文件,这个部分就不在本文进行分析了。
用同样的方法,对connect下断点,得到了访问dns服务器的堆栈信息:
#0 __libc_connect (fd=3, addr=addr@entry=..., len=16) at ../sysdeps/unix/sysv/linux/connect.c:26#1 0x00007ffff71b4b20 in reopen (statp=statp@entry=0x7ffff7dd1bc0 <_res>, terrno=terrno@entry=0x7fffffffc0a8, ns=ns@entry=0) at res_send.c:977#2 0x00007ffff71b5e0b in send_dg (ansp2_malloced=0x0, resplen2=0x0, anssizp2=0x0, ansp2=0x0, anscp=0x7fffffffd168, gotsomewhere=, v_circuit=, ns=0, terrno=0x7fffffffc0a8, anssizp=0x7fffffffc1d0, ansp=0x7fffffffc098, buflen2=0, buf2=0x0, buflen=38, buf=0x7fffffffc200 "\254\212\001", statp=) at res_send.c:1078#3 __res_context_send (ctx=ctx@entry=0x555555756530, buf=buf@entry=0x7fffffffc200 "\254\212\001", buflen=buflen@entry=38, buf2=buf2@entry=0x0, buflen2=buflen2@entry=0, ans=, ans@entry=0x7fffffffcd10 "cxaPfi", anssiz=, ansp=, ansp2=, nansp2=, resplen2=, ansp2_malloced=) at res_send.c:522#4 0x00007ffff71b34d1 in __GI___res_context_query (ctx=ctx@entry=0x555555756530, name=name@entry=0x555555554924 "baidu.com", class=class@entry=1, type=type@entry=1, answer=answer@entry=0x7fffffffcd10 "cxaPfi", anslen=anslen@entry=1024, answerp=0x7fffffffd168, answerp2=0x0, nanswerp2=0x0, resplen2=0x0, answerp2_malloced=0x0) at res_query.c:216#5 0x00007ffff71b428d in __res_context_querydomain (domain=0x0, answerp2_malloced=0x0, resplen2=0x0, nanswerp2=0x0, answerp2=0x0, answerp=0x7fffffffd168, anslen=1024, answer=0x7fffffffcd10 "cxaPfi", type=1, class=1, name=0x555555554924 "baidu.com", ctx=0x555555756530) at res_query.c:601#6 __GI___res_context_search (ctx=ctx@entry=0x555555756530, name=name@entry=0x555555554924 "baidu.com", class=class@entry=1, type=type@entry=1, answer=answer@entry=0x7fffffffcd10 "cxaPfi", anslen=anslen@entry=1024, answerp=0x7fffffffd168, answerp2=0x0, nanswerp2=0x0, resplen2=0x0, answerp2_malloced=0x0) at res_query.c:370#7 0x00007ffff73c7f0c in gethostbyname3_context (ctx=ctx@entry=0x555555756530, name=name@entry=0x555555554924 "baidu.com", af=af@entry=2, result=result@entry=0x7fffffffd7d0, buffer=buffer@entry=0x7fffffffda40 "\377\002", buflen=buflen@entry=1024, errnop=0x7ffff7fca440, h_errnop=0x7ffff7fca4a4, ttlp=0x0, canonp=0x7fffffffd7c8) at nss_dns/dns-host.c:218#8 0x00007ffff73c8928 in _nss_dns_gethostbyname3_r (name=name@entry=0x555555554924 "baidu.com", af=af@entry=2, result=result@entry=0x7fffffffd7d0, buffer=0x7fffffffda40 "\377\002", buflen=1024, errnop=errnop@entry=0x7ffff7fca440, h_errnop=0x7ffff7fca4a4, ttlp=0x0, canonp=0x7fffffffd7c8) at nss_dns/dns-host.c:164#9 0x00007ffff7ae7e6f in gaih_inet (name=name@entry=0x555555554924 "baidu.com", service=, req=req@entry=0x7fffffffdeb0, pai=pai@entry=0x7fffffffd9c8, naddrs=naddrs@entry=0x7fffffffd9c4, tmpbuf=tmpbuf@entry=0x7fffffffda30) at ../sysdeps/posix/getaddrinfo.c:885#10 0x00007ffff7ae9c84 in __GI_getaddrinfo (name=, service=, hints=0x7fffffffdeb0, pai=0x7fffffffdea0) at ../sysdeps/posix/getaddrinfo.c:2300#11 0x000055555555483b in main (argc=1, argv=0x7fffffffdfd8) at test.c:17
注意,这里connect的堆栈信息由于struct sockaddr的原因,无法判断是否真实访问的是8.8.8.8,因此我们可以尝试将其转换回(通过inet_ntoa转换ip,通过ntohs转换端口)struct sockaddr_in来分析,分析结果(IP地址,端口号)如下图:
因此我们得到了getaddrinfo的访问8.8.8.8 dns服务器的调用路径,其值如下:getaddrinfo-->gaih_inet->_nss_dns_gethostbyname3_r->gethostbyname3_context->__res_context_search->__res_context_querydomain->__res_context_query->__res_context_send->send_dg->reopen->__libc_connect 连接 dns服务器,解析dns
特别注意:
这里仅仅是描述了通过dns服务器得到ip的过程,其实相对于getaddrinfo的dns解析来说,这只是其中的一部分,还有通过类似nscd(有兴趣可以去看看man systemd-resolved)等等来解析的方式,这些内容感兴趣可以去看看。
后记
最后,回到了本文的开始,经过上述的分析后,我找到了我的问题的本质原因。我遇到的问题的本质原因是:由于某些特殊原因导致了connect 114.114.114.114:53 服务器的时候报错了,导致解析域名失败,当我换一个域名服务器(8.8.8.8)就解决了。
总的来说,本文从ping baidu.com入手,然后分析了ping的源码,得到了我们要分析的重点getaddrinfo。然后我们由于构造一个小例子来分析getaddrinfo的源码,最终得到了/etc/resolv.conf是因为什么原因生效的。
通过本文的分析,相信我们对DNS的解析过程是有了一个比较清晰的了解了,以后遇到类似的问题也能够有一个好的思路来解决问题。
参考文献
- 无
PS: 请尊重原创,不喜勿喷。PS: 要转载请注明出处,本人版权所有。PS: 有问题请留言,看到后我会第一时间回复。
关键词:
LinuxDNS分析从入门到放弃(记一次有趣的dns问题排查记录,ping 源码分析,getaddrinfo源码分析)
Linux三剑客grep、sed、awk(包括练习题)|环球热推荐
天天热讯:巨轮智能:公司近期经营情况正常 内外部经营环境未发生重大变化
美国《国家地理》回应传闻:不会停刊、不影响内容质量
新西兰升级禁塑令:违者将被罚款44万元 世界速递
【世界报资讯】IOS开发-实现一个高度自适应的UILabel和一个宽度自适应的UILabel
Kali Linux 配置系统代理_当前热闻
中外合作办学 授予中、英学士学位 凯里学院这个专业计划招生120人
终结日本队5连冠!中国女篮时隔12年再得亚洲杯冠军
惠普发布新款游戏显示器:2K IPS屏、240Hz高刷|播资讯
全球简讯:泰州市召开“泰惠农•金融服务乡村振兴”农业农村重大项目专题对接会
Jar包开发之【有之则用,无之则禁】|世界新要闻
CentOS 9 x64 使用 Nginx、Supervisor 部署 Go/Golang 服务
spring启动流程 (2) Bean实例化流程 世界短讯
【全球新视野】问界M5智驾版发布全新OTA升级 加入全新智驾领航辅助等功能
真世界霸主!任天堂第一方收入远超索尼、微软
6月北京口岸出入境人员突破88万,再创今年出入境流量新高 全球观点
特斯拉将采用线控转向技术 Yoke方向盘能否全面普及? 环球要闻
20万买“小奔驰”图什么?
卷疯了!全新马自达3昂克赛拉正式上市 9.99万到底值不值?_观点
中非经贸博览会指定用车,岚图梦想家到底哪里好? 焦点热议
AMD食言了!说好的显卡性能神技HYPR-RX跳票
至高优惠200元 华为MatePad Air 原野绿新色上市开启预售 天天快资讯
新机蓄势待发!Switch后续机型开发套件或已抵达西班牙-环球观热点
汪小菲“趁火打劫”成功,将接子女回北京,大s妥协原因引热议_全球热头条
大V吐槽极氪倒车影像“骗人”bug:让他撞了两次车
马斯克缺钱?推特限制用户浏览量:不开会员每天只能看1000条_今日视点
动态:硕士被曝制作全校学生颜值打分网站供人查看 人大回应
Python 使用 NetworkX
当前关注:excel图表制作折线图数据选择_excel图表制作折线图
华为智选车将建汽车独立门店 知情人士:经销商加盟 华为话语权更大
20万内仅有的换电SUV来了!吉利睿蓝7即将上市
切比雪夫距离
全球微动态丨日方首度确认!中国两栖攻击舰路过鹿儿岛
俩南方小伙山东旅游点6个菜吃不完 被北方菜“上了一课”-世界短讯
广东一电摩自燃 30辆车被连累烧成空壳!千万别在室内充电
俄罗斯恢复飞往古巴的定期航班
人大金仓学习之一_kwr的简单学习_环球看点
前端Vue基于腾讯地图Api实现的选择位置组件 返回地址名称详细地址经纬度信息|世界焦点
今日要闻!民主测评软件需求分析与实现
6大人争接萌娃放学 最后姥爷赢麻了:画面让网友笑翻-环球快资讯
美国一女子去世7只猫继承217万遗产引热议:上百人抢着领养
公共气象服务中心:预警“叫应”联动服务信息化建设_每日热门
每日看点!选读SQL经典实例笔记01_检索和排序
学霸、体育才女!谷爱凌大一课程全A 曾自称成绩100%自己努力得到的
华硕全球首发RTX 4060 Ti神卡:能扩展M.2 SSD
当前短讯!威马疑又停薪,仅发中高层工资!“讨债大军”攻陷官方微博
国科大校长谈龙芯之母说着说着就哭了:别让“卡脖子”遏制我们发展 当前报道
【WALT】update_window_start() 代码详解
国外RTX 4090销售陷入困境 愁坏了很多零售商
孙女给生活不能自理爷爷洗澡引争议 当事人:孝心不分男女 天天头条
升级iOS 17还要交钱?跟iOS 16对比后拔草了!立省688元
今日播报!Apple Watch新款感知不强!500块的S4最香
做“有温度”的就业指导服务|世界新视野
每日热文:大姨妈不正常怎么办吃什么好呢_大姨妈不正常怎么办
【世界速看料】茅坑里的石头是哪种人_茅坑里的石头是什么意思
【聚看点】go src - sync.Map
环球观天下!Web安全-渗透测试-权限提升01
焦点快报!116-104!山东高速力克北京首钢,山东试训外援首秀轻取19分
63岁男子向熊猫投掷苹果惹众怒 后果来了:被终身禁入
宝镇
天玑9200+性价王者预定!Redmi K60 Ultra第三方保护壳现身|全球新视野
支持正版:英国为采购Office刚花了71亿|天天快看
全球热资讯!7月新农合再涨40元,一市明确每人590元,今年你还交吗?
长城站起来!哈弗枭龙系列第1万台下线:6月热销6098台暴增97%
复兴号正式在青藏铁路投入运行:海拔3000米 零下40度也能跑
曼高德谈《夺宝奇兵5》
天天快讯:传奇设计大师去世:“我从不设计丑陋东西”
焦点精选!第一部8.0分不值一提!美国年度科幻大片续集来了
协鑫宣布年产36万吨储能正极材料项目今日投产-世界热讯
张雪峰老师推荐的十大高薪专业引发热议:计算机类霸榜 文科中仅法语入围 天天速读
丰田章男工资曝光:9.99亿日元丰田汽车史上最高! 环球微头条
RPM安装的Oracle19c 修改init.ora进行修复以及最简单开机启动Oracle的方法 世界百事通
markdown终极指南 观点
100%纯棉、亲肤舒适:布静观纯棉短袖13元、长袖16元
环球视讯!多地高温难耐 黑龙江却遭遇特大冰雹:砸碎几乎整栋楼玻璃
环球新消息丨安卓性能标杆!一加Ace 2 Pro来了:5200mAh+骁龙8 Gen2
米体:汉达可能降薪续约留在国米,下赛季担任二号门将 全球微动态
mosquitto的基本参数使用
全球热议:探究直播app源码技术:视频上传功能
当前资讯!02修剪标准&&方法
环球滚动:ThinkPHP6.0 链式SQL语句
【世界速看料】见证历史!苹果成全球首家市值3万亿美元公司 意味着什么?
男生旅行3年收集50余个城市水土:覆盖30个省份 比打卡拍照更有意义
云南男子外出干活遇超大菌子 网友羡慕:菌之大一锅炖不下_当前聚焦
网友吐槽一条街三四十个井盖 官方回应:雨污分流、将铺上沥青
当前热议!五年中考三年模拟八上物理答案
全球观热点:MinIO-对象存储简单使用
JS必学的11个工具方法(避免重复造轮子) 世界快看
IDA的使用2_全球新视野
荷兰DUV光刻机一律管制出口?一文看懂|环球快播
埃安6月销量45013辆创历史新高 今年已卖出比亚迪一个月销量
特斯拉加入价格乱战!买这两款车最高优惠4.5万元
国内高端手机市场除了苹果iPhone 还能有谁?! 焦点要闻
2023年全国铁路暑期运输启动:满血复活 暴涨超70%
焦点热议:使用Gitee或GitHub托管Maven仓库JAR包的便捷方法
灭霸演员是谁_ 芝士回答
世界短讯!心爱的小乌龟死了:主人把它做成《七龙珠》龟仙人手办!
担心的事情发生了!泰国女游客卷入电动步道腿被夹断
火车站保洁阿姨不慎弄脏乘客衣服跪地道歉 公司回应:已和解 世界观焦点