当前位置:首页 » 编程软件 » nginx源码脚本

nginx源码脚本

发布时间: 2023-07-18 08:43:29

A. 如何解读Nginx源码

前提:
1、首先nginx是c语言编写的,你必须知识要有C语言的编程基础,否则很痛苦
2、了解web服务器,反向代理的基本知识,以及HTTP协议,TCP/IP协议的基本知识
如果你已经有丰富的经验,或者是大牛,那前面的前提就是废话,可以略过。
看源码准备:
1、找官网,找贡献者的博客去了解NGINX是做什么的,有什么特性,性能,功能,架构等
2、下载源代码,从分析main函数开始,大致了解启动流程,初始化以及一些程序的启动准备
3、建议找到request逻辑,分析下对请求的整个处理流程,不用很细,慢慢来,一口吃不了大胖子,有问题就先记上再说
4、根据分析request的经验,拓展分析下nginx的模块,处理链,以及封装的数据结构如ngx_str_t,ngx_event_t等数据结构
5、到网上找个例子,自己动手去写个模块,或修改某个处理逻辑,你一定会遇到问题,这时你可以通过GDB等工具进行分析和调试,这样加深了你的理解
6、动手写代码,看源码,调试,重复这个过程。
其他
多在网络上找资源和志同道和的技术爱好者或牛人,多交流沟通。
坚持一年,你会有突飞猛进的成绩。good luck

B. nginx 源码 epoll模块在哪个文件

linux平台上,Nginx使用epoll完成事件驱动,实现高并发;本文将不对epoll本身进行介绍(网上一堆一堆的文章介绍epoll的原理及使用方法,甚至源码分析等),仅看一下Nginx是如何使用epoll的。

Nginx在epoll模块中定义了好几个函数,这些函数基本都是作为回调注册到事件抽象层的对应接口上,从而实现了事件驱动的具体化,我们看如下的一段代码:

[cpp] view plain print?
ngx_event_mole_t ngx_epoll_mole_ctx = {
&epoll_name,
ngx_epoll_create_conf, /* create configuration */
ngx_epoll_init_conf, /* init configuration */
{
ngx_epoll_add_event, /* add an event */
ngx_epoll_del_event, /* delete an event */
ngx_epoll_add_event, /* enable an event */
ngx_epoll_del_event, /* disable an event */
ngx_epoll_add_connection, /* add an connection */
ngx_epoll_del_connection, /* delete an connection */
NULL, /* process the changes */
ngx_epoll_process_events, /* process the events */
ngx_epoll_init, /* init the events */
ngx_epoll_done, /* done the events */
}
};

这段代码就是epoll的相关函数注册到事件抽象层,这里所谓的事件抽象层在前面的博文中有提过,就是Nginx为了方便支持和开发具体的I/O模型,从而实现的一层抽象。代码后面的注释将功能说明得很详细了,本文就只重点关注ngx_epoll_init和ngx_epoll_process_events两个函数,其他几个函数就暂且忽略了。

ngx_epoll_init主要是完成epoll的相关初始化工作,代码分析如下:

[cpp] view plain print?
static ngx_int_t
ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
ngx_epoll_conf_t *epcf;
/*取得epoll模块的配置结构*/
epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_mole);
/*ep是epoll模块定义的一个全局变量,初始化为-1*/
if (ep == -1) {
/*创一个epoll对象,容量为总连接数的一半*/
ep = epoll_create(cycle->connection_n / 2);
if (ep == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"epoll_create() failed");
return NGX_ERROR;
}
}
/*nevents也是epoll模块定义的一个全局变量,初始化为0*/
if (nevents < epcf->events) {
if (event_list) {
ngx_free(event_list);
}

/*event_list存储产生事件的数组*/
event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
cycle->log);
if (event_list == NULL) {
return NGX_ERROR;
}
}
nevents = epcf->events;
/*初始化全局变量ngx_io, ngx_os_is定义为:
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
ngx_readv_chain,
ngx_udp_unix_recv,
ngx_unix_send,
ngx_writev_chain,
0
};(位于src/os/unix/ngx_posix_init.c)
*/
ngx_io = ngx_os_io;
/*这里就是将epoll的具体接口函数注册到事件抽象层接口ngx_event_actions上。
具体是上文提到的ngx_epoll_mole_ctx中封装的如下几个函数
ngx_epoll_add_event,
ngx_epoll_del_event,
ngx_epoll_add_event,
ngx_epoll_del_event,
ngx_epoll_add_connection,
ngx_epoll_del_connection,
ngx_epoll_process_events,
ngx_epoll_init,
ngx_epoll_done,
*/
ngx_event_actions = ngx_epoll_mole_ctx.actions;
#if (NGX_HAVE_CLEAR_EVENT)
/*epoll将添加这个标志,主要为了实现边缘触发*/
ngx_event_flags = NGX_USE_CLEAR_EVENT
#else
/*水平触发*/
ngx_event_flags = NGX_USE_LEVEL_EVENT
#endif
|NGX_USE_GREEDY_EVENT /*io的时候,直到EAGAIN为止*/
|NGX_USE_EPOLL_EVENT; /*epoll标志*/
return NGX_OK;
}

epoll初始化工作没有想象中的复杂,和我们平时使用epoll都一样,下面看ngx_epoll_process_events,这个函数主要用来完成事件的等待并处理。

[cpp] view plain print?
static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int events;
uint32_t revents;
ngx_int_t instance, i;
ngx_uint_t level;
ngx_err_t err;
ngx_log_t *log;
ngx_event_t *rev, *wev, **queue;
ngx_connection_t *c;
/*一开始就是等待事件,最长等待时间为timer;nginx为事件
专门用红黑树维护了一个计时器。后续对这个timer单独分析。
*/
events = epoll_wait(ep, event_list, (int) nevents, timer);
if (events == -1) {
err = ngx_errno;
} else {
err = 0;
}
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
/*执行一次时间更新, nginx将时间缓存到了一组全局变量中,方便程序高效的获取事件。*/
ngx_time_update();
}
/*处理wait错误*/
if (err) {
if (err == NGX_EINTR) {
if (ngx_event_timer_alarm) {
ngx_event_timer_alarm = 0;
return NGX_OK;
}
level = NGX_LOG_INFO;
} else {
level = NGX_LOG_ALERT;
}
ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
return NGX_ERROR;
}
/*wait返回事件数0,可能是timeout返回,也可能是非timeout返回;非timeout返回则是error*/
if (events == 0) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"epoll_wait() returned no events without timeout");
return NGX_ERROR;
}
log = cycle->log;
/*for循环开始处理收到的所有事件*/
for (i = 0; i < events; i++) {

/*取得发生此事件的连接*/
c = event_list[i].data.ptr;
instance = (uintptr_t) c & 1;
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
/*获得该连接上的读事件*/
rev = c->read;
。。。。。。。。。。。。。

/*取得发生一个事件*/
revents = event_list[i].events;

/*记录wait的错误返回状态*/
if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
"epoll_wait() error on fd:%d ev:%04XD",
c->fd, revents);
}
if ((revents & (EPOLLERR|EPOLLHUP))
&& (revents & (EPOLLIN|EPOLLOUT)) == 0)
{
/*
* if the error events were returned without EPOLLIN or EPOLLOUT,
* then add these flags to handle the events at least in one
* active handler
*/
revents |= EPOLLIN|EPOLLOUT;
}
/*该事件是一个读事件,并该连接上注册的读事件是active的*/
if ((revents & EPOLLIN) && rev->active) {
if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
rev->posted_ready = 1;
} else {
rev->ready = 1;
}

/*事件放入相应的队列中;关于此处的先入队再处理,在前面的文章中已经介绍过了。*/
if (flags & NGX_POST_EVENTS) {
queue = (ngx_event_t **) (rev->accept ?
&ngx_posted_accept_events : &ngx_posted_events);
ngx_locked_post_event(rev, queue); /*入队*/
} else {
rev->handler(rev);
}
}
wev = c->write;
/*发生的是一个写事件,和读事件完全一样的逻辑过程*/
if ((revents & EPOLLOUT) && wev->active) {
if (flags & NGX_POST_THREAD_EVENTS) {
wev->posted_ready = 1;
} else {
wev->ready = 1;
}
/*先入队再处理*/
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
}
}
return NGX_OK;
}

本文将关注的两个epoll函数也就这么一点代码了,但整个epoll还有添加事件和删除事件等的相关函数,代码都很简单,本文就不做具体的分析了。

写到此处的时候,我感觉epoll模块没有分析的足够详细,或者说是没有足够的理解作者的用意,如果你有更好的理解,希望能够告诉我。或许,随着后面的分析,能够逐渐的真正明白吧。

C. nginx编译安装服务启动脚本在哪

在你编译是 --prefix=指定的目录下有一个bin目录,里面有一个nginx启动脚本,如果没有指定,默认在/usr/local/nginx下,即/usr/local/nginx/sbin/nginx

D. 如何用Nginx源码制作RPM包的详解

1、查看操作系统版本和内核版本

2、创建相关目录

/usr/src/redhat/SOURCES //存放源代码,补丁,图标等文件。
/usr/src/redhat/SPECS //存放用于管理rpm制作进程的spec文件。
/usr/src/redhat/BUILD //解压后的文件存放在这里。
/usr/src/redhat/RPMS //存放由rpmbuild制作好的二进制包。
/usr/src/redhat/SRPMS //存放由rpmbuild制作好的源码包。

3、下载Nginx源码包

下载源码包到SOURCES目录,不需要解压。

4、手工创建SPEC文件,由于spec文件是由spec语言编写的,请注意spec语言的语法。

SPEC文件内容如下:



#############################
# Example Spec File For Nginx
# Edited By LaoXu 7.Mar.2013
#############################
Summary: High Performance Web Server
Name: nginx
Version: 1.3.9
Release: el5
License: GPL
Group: Applications/Server
Source:
URL:
Distribution: Linux
Packager: XuYuanzhen <absolutey.>

%description
nginx [engine x] is a HTTP and reverse proxy server, as well as a mail proxy server
%prep
rm -rf $RPM_BUILD_DIR/nginx-1.3.9
zcat $RPM_SOURCE_DIR/nginx-1.3.9.tar.gz | tar -xvf -
%build
cd nginx-1.3.9
./configure --prefix=/usr/local/nginx
make
%install
cd nginx-1.3.9
make install
%preun
if [ -z "`ps aux | grep nginx | grep -v grep`" ];then
killall nginx >/dev/null
exit 0
fi
%files
/usr/local/nginx5、开始RPM制作

在制作RPM包之前,需要安装必要的编译工具,如rpmbuild,gcc等。

开始编译生成rpm包

cd /usr/src/RedHat/SPECS/

rpmbuild -bb nginx.spec //-ba 参数表示同时生成二进制包和源码包 -bb 参数表示只生成二进制包

经过一段时间的编译后最终生成了rpm包文件

如图所示,在/usr/src/redhat/RPMS/x86_64/该目录下生成了我们需要的rpm包,由于我编译的操作系统平台是64bit的,所以生成的rpm包也是64位的文件。在指定的目录下生成RPM,通常用%_topdir变量,需要在宏配置文件中指定,配置文件称为macrofiles,它们通常为 /usr/lib/rpm/macros:/usr/lib/rpm/macros.*:~/.rpmmacros,这个在rhel 5.8中可以通过rpmbuild --showrc | grep macrofiles 查看,我们这里在.rpmmacros文件中定义了生产rpm包的路径为/usr/src/redhat

最后安装生成的rpm包

至此Nginx源码制作并安装成功!

E. 怎么编译安装nginx1.8.1

要编译安装Nginx,首先我们要安装依赖包 pcre-devel 和 zlib-devel:
# yum install pcre-devel zlib-devel -y
程序默认是使用 nobody 身份运行的,我们建议使用 nginx 用户来运行,首先添加Nginx组和用户,不创建家目录,不允许登陆系统
# groupadd nginx
# useradd -M -s /sbin/nologin -g nginx nginx

准备工作完成后就是下载编译安装Nginx了,可以从我提供的网盘下载,也可以去Nginx的官网下载。
首先解压源码包:
# tar xf nginx-1.4.4.tar.gz
然后 cd 到解压后的目录就可以执行 ./configure 了
# cd nginx-1.4.4
指定安装目录和运行时用的属主和属组,并启用状态监控模块等
# ./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_mole \
--with-http_flv_mole \
--with-http_stub_status_mole \
--with-http_gzip_static_mole \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
--http-scgi-temp-path=/var/tmp/nginx/scgi \
--with-pcre
等配置完成后就可以 make && make install 了
# make && make install
# mkdir /var/tmp/nginx/client/ -pv

等编译安装完成后在 /usr/local 下就会出现 Nginx 这个目录了,进入这个目录后发现目录非常简单。它的配置文件存放在 conf 目录中,网页文件存放在 html 中,日志文件存放在 logs 中,sbin 目录下只有一个可执行程序 "nginx"
接下来我们简单的为它提供一个服务脚本吧!
# vim /etc/init.d/nginx
新建文件/etc/rc.d/init.d/nginx,内容如下:
#!/bin/bash
# chkconfig:235 85 15
# description: Nginx is an HTTP server
. /etc/rc.d/init.d/functions
start() {
echo "Start..."
/usr/local/nginx/sbin/nginx &> /dev/null
if [ $? -eq 0 ];then
echo "Start successful!"
else
echo "Start failed!"
fi
}

stop() {
if killproc nginx -QUIT ;then
echo "Stopping..."
fi
}

restart() {
stop
sleep 1
start
}

reload() {
killproc nginx -HUP
echo "Reloading..."
}

configtest() {
/usr/local/nginx/sbin/nginx -t
}

case $1 in
start)
start ;;
stop)
stop ;;
restart)
restart ;;
reload)
reload ;;
configtest)
configtest ;;
*)
echo "Usage: nginx {start|stop|restart|reload|configtest}"
;;
esac

之后给这个文件可执行权限:
# chmod +x /etc/init.d/nginx
好了,现在可以使用 start,stop 这些参数控制Nginx服务了

由于脚本是我自己写的,还有许多不尽人意的地方,欢迎大家修改和完善!
现在我们就试试启动服务看看效果吧:
# service nginx start
记得关闭 SElinux 和 iptables 防火墙哦,
# service iptables stop
# setenforce 0
接下来就在浏览器中访问你服务的IP看看效果吧!是不是出项了欢迎的字样呢

接下来就研究下 Nginx 的配置文件吧!
# vim /usr/local/nginx/conf/nginx.conf
各项参数的意义如下:
worker_processes 1; 工作进程数量

error_log logs/error.log; 日志文件位置
pid logs/nginx.pid; pid文件位置
worker_connections 1024; 没进程的连接数
listen 80; 监听端口
server_name localhost; 主机名
root html; 网站根目录
index index.html index.htm; 网站索引页
error_page 500 502 503 504 /50x.html; 访问错误页面
剩下的其他被注释掉的代码块:
location ~ \.php$ { . . . . . . } 对PHP的支持,需要安装PHP
server { . . . . . . } 添加server代码块能添加虚拟主机
剩下还有监听443端口的超文本传输安全协议 HTTPS server 需要在编译Nginx时添加ssl的支持

接下来我们试着添加一台虚拟主机吧,虚拟主机的添加可以基于端口,可以基于IP,也可以基于主机名,我们挨个来看看:
基于端口:
首先编辑配置文件,添加server代码块,记得要写到http{ . . . . . . }这个大的代码块中。
server {
listen 8080;
server_name localhost;

location / {
root /var/www/html;
index index.html index.htm;
}
}
这样就添加了一个监听8080端口的服务,你也可以定义自己喜欢的端口哦。
接下来检查下配置文件有没有问题,如果最后一个单词显示successful就代表没问题了,可以重新启动Nginx了
# service nginx configtest
# service nginx restart
接下来就给第二个虚拟主机写一个index吧!首先创建目录
# mkdir -pv /var/www/html
# echo '<h1>Hi! This is 8080!</h1>' > /var/www/html/index.html
好了 接下来试着在浏览器中访问访问,记得第二个主机要加上端口访问哦

现在试着用不同的IP建立虚拟主机吧!我们可以在一块网卡上绑定多个IP地址的方式来实现
# ifconfig eth0:0 10.0.0.4/8
记得把IP换成你自己的哦!然后ifconfig看看是不是多出来一个网卡IP了呢
让后继续修改配置文件,这回要修改两个地方,一个是原本自带的站点的 listen 项,一个是自己添加的站点的 listen 项。
基于IP:
server {
listen 10.0.0.3:80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
}

server {
listen 10.0.0.4:80;
server_name localhost;

location / {
root /var/www/html;
index index.html index.htm;
}
}
让他们只监听不同的IP,用相同的端口

接下来再浏览器上用不同的IP来访问试试吧,及的还得重启Nginx,先检查一下,出现错误了看看哪里配置的不对,然后就可以重启了。
# service nginx congiftest
# service nginx restart
如果配置给网卡的第二个IP不想要了,把它停掉就可以了
# ifconfig eth0:0 down
再 ifconfig 看看是不是没有了呢

现在试试用不同的主机名吧!也是企业用的最多的方式。我们把两个站点的listen项都改为80,然后修改service_name项为定义的主机名
基于主机名:

server {
listen 80;
server_name ybmq.com;

location / {
root html;
index index.html index.htm;
}
}

server {
listen 80;
server_name zhzz.com;

location / {
root /var/www/html;
index index.html index.htm;
}
}

然后重启Nginx吧!

可是我们在浏览器上怎么通过域名访问呢?要知道我们访问 啊,qq 啊之类的是通过DNS服务器的,难道我们还要配置一台DNS服务器?其实不然,我们通过修改客户机的 hosts 文件就可以了。hosts文件是一个本地的域名解析文件,我们要解析哪些域名只要把域名和对应的IP写到一起就可以了。在Windows XP之后的系统中,这个文件位于:
C:\Windows\System32\drivers\etc\hosts
我们用文本编辑器打开,添加两个相同的IP对应的两个不同的主机名就可以了。
如下图所示

如果你打开这个文件发现已经有很多IP地址了,可以直接在最后加入这两行,也可以直接清空这个文件,不会有什么问题的。这个文件的用途还可以屏蔽一些网站哦,只需要把网址对于的IP改为 127.0.0.1 也就是本地回环地址,浏览器查询域名对应的IP时时先通过查询这个文件的,如果查询到了,不管对错都不会访问DNS服务器了,所以我们给它一个错误的地址,那它一辈子也打不开被屏蔽掉的网站了。
好了 接下来就在浏览器中试试用用域名访问你的两个站点吧。
如果大家还用IP访问会是什么情况呢?我不说了,大家还是自己测试吧 哈哈o(^▽^)o

F. Linux系统下nginx日志每天定时切割的脚本写法

下面是deepvps自己用的自动每天定时切割Nginx日志的`脚本,很方便很好用,推荐给大家使用。本脚本也是参考了张宴老师的文章,再次感谢张宴老师。

1、创建脚本/usr/local/nginx/sbin/cut_nginx_log.sh

vi /usr/local/nginx/sbin/cut_nginx_log.sh

输入以下内容:

#!/bin/bash

# This script run at 00:00

# The Nginx logs path

logs_path=”/home/www/logs/”

mkdir -p ${logs_path}$(date -d “yesterday” +”%Y”)/$(date -d “yesterday” +”%m”)/

mv ${logs_path}access.log ${logs_path}$(date -d “yesterday” +”%Y”)/$(date -d “yesterday” +”%m”)/access_$(date -d “yesterday” +”%Y%m%d”).log

kill -USR1 `cat /usr/local/nginx/nginx.pid`

2、设置crontab,每天凌晨00:00切割nginx访问日志

crontab -e

输入以下内容:

00 00 * * * /bin/bash /usr/local/nginx/sbin/cut_nginx_log.sh

G. 求大神指导Centos7 源码编译安装Nginx+PHP 配置动静分离

这个是我的服务的实际 将配置Nginx实现动静分离,对php页面的请求转发给LAMP处理,而静态页面交给Nginx,以实现动静分离。客户请求静态数据给Nginx,Nginx直接应答客户端,当请求动态数据到Nginx时,Nginx让客户端去找LAMP,通过代理的方式,LAMP就和客户端连接了。分别配置动态分离和静态分离

(1)架设并调试后端LAMP架构,指定的域名,IP地址为xxxx,创建动态页面test.php。

(2)配置Nginx(xxxx)处理动态页面请求,并把域名改为 chaodiquan.com 在server{};段中加入以下代码,检测语法后,重启Nginx

(3)客户端输入xxxx/test.php 成功后动态分离就实现了,接下来再配置静态分离

(4)配置Nginx处理静态页面请求,在server{};中加入以下代码,检测语法后,重启Nginx

location ~ .*.(gif|jpg|jpeg|bmp|swf)$ { #这段代码意思是任意网址以这5种格式为结尾就到Nginx根目录下的html文件夹寻找资源

root html;
expires 1d; #缓存一天}

(5)在nginx的html目录中,放入图片aa.jpg,然后在apache的动态测试页test.php中添加

<html>
<body>
<img src="aaaa/aa.jpg">
</body>
</html>

(6)客户端输入xxxx/test.php测试,由于test.php是动态页面,因此客户端会找到LAMP架构中的Apache,然后调取图片aa.jpg是静态数据,所以从Nginx提取,最后反馈给客户端。这个是

H. 源码安装nginx需要安装哪些东西

nginx配置里面配置一个server段,然后把网站的目录,域名,别名等配置好就可以了。想要好管理配置,用include加个文单花厕拘丿饺搽邪敞矛件,里面专门配置server段

I. nginx多server日志分割脚本

1,配置多个server日志只要在$website变量增加并用空格分开就行。

2,循环创建日志目录

3,分割后用xz 压缩,当然没安装可以用gzip bzip2等等。

4,注意我配置nginx日志文件名为 "access_{{站点网站}}.log" "error_{{站点网站}}.log"

复制代码 代码如下:

# !/usr/bin/bash

log_dir="/usr/local/nginx/logs"

back_log_dir="/disk110/nginx_log"

time=`date +%Y%m%d-%H:%M:%S`

website="www.test1.com www.test2.com www.test3.com";

for i in $website

do

if [ ! -d ${back_log_dir}/${i} ]

then

mkdir ${back_log_dir}/${i}

fi

done

for i in $website

do

if [ -s ${log_dir}/access_${i}.log ]

then

mv ${log_dir}/access_${i}.log ${back_log_dir}/${i}/access_${time}.log

fi

if [ -s ${log_dir}/error_${i}.log ]

then

mv ${log_dir}/error_${i}.log ${back_log_dir}/${i}/error_${time}.log

fi

done

kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

for i in $website

do

if [ -s ${back_log_dir}/${i}/access_${time}.log ]

then

xz ${back_log_dir}/${i}/access_${time}.log

fi

if [ -s ${back_log_dir}/${i}/error_${time}.log ]

then

xz ${back_log_dir}/${i}/error_${time}.log

fi

done

热点内容
项目编译慢 发布:2025-02-06 16:53:48 浏览:379
python处理excel文件 发布:2025-02-06 16:36:09 浏览:441
算法相对定位 发布:2025-02-06 16:32:42 浏览:727
java程序的编译和执行 发布:2025-02-06 16:21:45 浏览:419
什么是淘宝帐号和密码 发布:2025-02-06 16:21:36 浏览:497
解压前面签 发布:2025-02-06 16:02:00 浏览:326
华硕访问点 发布:2025-02-06 15:56:57 浏览:333
excel拼接sql 发布:2025-02-06 15:50:10 浏览:503
加密手机直播 发布:2025-02-06 15:49:31 浏览:537
自带ftp服务器好用吗 发布:2025-02-06 15:26:11 浏览:112