LINUXQQ

四月 22, 2011

python AbstractFormatter

Filed under: python — admin @ 4:29 下午

模糊的搞懂了什么意思

HTMLParser(AbstractFormatter(DumbWriter(StringIO)))  ”’ 使用HTMLParser的方法进行处理,StringIO是从内存中读取数据,DumbWriter将事件流转换为存文本文档”’
主要是AbstractFormatter 查了下相关资料

formatter 模块
formatter 模块提供了一些可用于 htmllib 的格式类( formatter classes ).
这些类有两种, formatter 和 writer . formatter 将 HTML 解析器的标签和数据流转换为适合输出设备的事件流( event stream ), 而 writer 将事件流输出到设备上.
大多情况下, 你可以使用 AbstractFormatter 类进行格式化. 它会根据不同的格式化事件调用 writer 对象的方法. AbstractWriter 类在每次方法调用时打印一条信息.

 

HTMLParser是python用来解析html的模块。它可以分析出html里面的标签、数据等等,是一种处理html的简便途径。HTMLParser采用的是一种事件驱动的模式,当HTMLParser找到一个特定的标记时,它会去调用一个用户定义的函数,以此来通知程序处理。它主要的用户回调函数的命名都是以handler_开头的,都是HTMLParser的成员函数。当我们使用时,就从HTMLParser派生出新的类,然后重新定义这几个以handler_开头的函数即可。这几个函数包括:
handle_startendtag  处理开始标签和结束标签
handle_starttag     处理开始标签,比如<xx>
handle_endtag       处理结束标签,比如</xx>
handle_charref      处理特殊字符串,就是以&#开头的,一般是内码表示的字符
handle_entityref    处理一些特殊字符,以&开头的,比如 &nbsp;
handle_data         处理数据,就是<xx>data</xx>中间的那些数据
handle_comment      处理注释
handle_decl         处理<!开头的,比如<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
handle_pi           处理形如<?instruction>的东西
    这里我以从网页中获取到url为例,介绍一下。要想获取到url,肯定是要分析<a>标签,然后取到它的href属性的值。下面是代码:

#-*- encoding: gb2312 -*-
import HTMLParser

class MyParser(HTMLParser.HTMLParser):
    def __init__(self):
        HTMLParser.HTMLParser.__init__(self)        
        
    def handle_starttag(self, tag, attrs):
        # 这里重新定义了处理开始标签的函数
        if tag == ’a':
            # 判断标签<a>的属性
            for name,value in attrs:
                if name == ’href’:
                    print value
        

if __name__ == ’__main__’:
    a = ’<html><head><title>test</title><body><a href=”http://www.163.com”>链接到163</a></body></html>’
    
    my = MyParser()
    # 传入要分析的数据,是html的。
    my.feed(a)

class HTMLParser.HTMLParser:使用HTMLParser 的实例,填充HTML数据,并在开始和结束标记间调用函数.HTMLParser类意味着重载.和 htmllib 的分析器不同,this parser并不检测和开始标记对应的结束标记

HTMLParser 实例有如下的方法:
HTMLParser.reset()  #重置实例.所有未处理的数据都会丢失.在初始化时自动调用.
HTMLParser.feed(data) #给分析器喂食.在由完整元素构成的情况下工作;不完整数据情况下,会进行缓冲知道更多数据加进来或者 close() 被调用.
HTMLParser.close()  #处理所有缓冲数据.这个方法可以被派生类重定义,以便在输入结束后处理额外的事情,重定义的版本也要调用 HTMLParser 基类的 close() 方法.
HTMLParser.getpos() #返回当前行数和列数
HTMLParser.get_starttag_text() #返回最近打开过得开始标记处的文本.通常不会用到
HTMLParser.handle_starttag(tag, attrs) #该方法用来处理一个标记的开始.tag参数是tag的名字的小写化.attrs参数是一个list,由(name,value)组成,反映了<>里面的属性. name会被翻译成小写字母,在value中的引号也被移除了,字符实体引用也会被替换.例如,有个 tag<A HREF=”http://www.cwi.nl/”> ,那么使用该方法就该这么做: handle_starttag(‘a’, [('href','http://www.cwi.nl/')])
HTMLParser.handle_startendtag(tag, attrs) #和handle_starttag()类似,用来处理XHTML风格的空标签(<a …/>).可能被子类重载
HTMLParser.handle_endtag(tag) #该方法用来处理元素结束标记.可以被派生类重载;基类什么也不做. tag参数是tag的name转化来的小写字母.
HTMLParser.handle_data(data) #该方法用来处理随机的数据.
HTMLParser.handle_charref(name) #处理 &#ref 格式的字符引用.
HTMLParser.handle_entityref(name)  #处理一般的 &name 格式的实体引用. name 是一个一般的实体引用.
HTMLParser.handle_comment(data) #处理遇到注释的情况.注释参数为在——和——之间的字符串文本,而不是分隔符自身.例如 <!–text–> ,该方法将调用’text’.
HTMLParser.handle_decl(decl) #当分析器遇到SGML声明时调用此方法. decl 参数是 <!…> 标记里的整个内容.
HTMLParser.handle_pi(data) #处理命令, data 参数包含整个的处理命令.例如 <?proc color=’red’> ,该方法应写成 handle_pi(“proc color=’red’”).

使用实例:

#!/usr/bin/python
#-*- encoding: utf-8 -*-

import HTMLParser
class MyParser(HTMLParser.HTMLParser):
    def __init__(self):
        HTMLParser.HTMLParser.__init__(self)               
    def handle_starttag(self, tag, attrs):
       
# 这里重新定义了处理开始标签的函数
        if tag == ‘a’:
            # 判断标签<a>的属性
            for name,value in attrs:
                if name == ‘href’:
                    print value
       
if __name__ == ‘__main__’:
    a = ‘<html><head><title>test</title><body><a href=”http: //www.163.com”>链接到163</a><a href=”
http://www.linuxqq.net“>焦点</a></body></html>’
    my = MyParser()
    # 传入要分析的数据,是html的。
    my.feed(a)

运行结果:

www.163.com www.linuxqq.net

http: //www.163.com
http://www.linuxqq.net
handle_startendtag 处理开始标签和结束标签
handle_starttag     处理开始标签,比如<xx>
handle_endtag       处理结束标签,比如</xx>
handle_charref      处理特殊字符串,就是以&#开头的,一般是内码表示的字符
handle_entityref    处理一些特殊字符,以&开头的,比如 &nbsp;
handle_data         处理数据,就是<xx>data</xx>中间的那些数据
handle_comment      处理注释
handle_decl         处理<!开头的,比如<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
handle_pi           处理形如<?instruction>的东西

四月 21, 2011

urlparse TypeError: ‘module’ object is not callable

Filed under: python — admin @ 11:40 上午

import urllib
import urllib2
import urlparse
url=’http://www.linuxqq.net’
aa=urlparse(url)[1]
print aa
报错 纠结了 看下书

原来urlparse 是模块 模块怎么能直接输出呢

适当的改了下

import urllib
import urllib2
import urlparse
url=’http://www.linuxqq.net’
aa=urlparse.urlparse(url)[1]
print aa

OK正常啦 自己小鸟啦

四月 14, 2011

You could try using –skip-broken to work around the problem

Filed under: linux — admin @ 10:07 上午

Error: Missing Dependency: perl(Compress::Raw::Zlib) = 2.024 is needed by package perl-IO-Compress-2.030-1.el5.rf.noarch (dag)
 You could try using –skip-broken to work around the problem
 You could try running: package-cleanup –problems
                        package-cleanup –dupes
                        rpm -Va –nofiles –nodigest
The program package-cleanup is found in the yum-utils package.
[root@www ~]# 

解决: 

yum –skip-broken update

四月 8, 2011

flv 开源的网页播放器

Filed under: 乱7八糟 — admin @ 3:57 下午

发现了一个好用的JW PLAYER 播放器记录下

JW PLAYER 是一个界面简洁、功能齐全的在线flv flash播放器.有着很多可选控制参数。
多个参数可以混合使用,下面选择几个作简要说明:
file (FLV文件的地址,如果不设置则默认为jw player flv网页播放器同目录的video.flv)
autostart (是否允许自动播放,”true”或者”false”)
image (未播放时的预览图片,只支持JPEG格式)
repeat (是否重复播放)
clicktext (开始时显示的文字,默认是”click to play”)

下载的最新版本flv网页播放器调用说明:
<script type=”text/javascript” src=”swfobject.js”></script>
<script type=”text/javascript”>
var s1 = new SWFObject(“player.swf”,”ply”,”190″,”180″,”0″,”#FFB901″);
s1.addParam(“allowfullscreen”,”true”);
s1.addParam(“allowscriptaccess”,”always”);
s1.addParam(“flashvars”,”file=/flv/video.flv&image=/flv/preview.jpg&autostart=true”);
s1.write(“container”);
</script>

说明:
autostart=true是设置自动播放,如果把true改为flash则不自动播放。
file=/flv/video.flv是设置播放flv文件的位置。
image=/flv/preview.jpg是设置未播放时的预览图片,只支持JPG的图片。

flv网页播放器JW Player使用说明(适用旧版本):

一般调用程序代码
<object type=”application/x-shockwave-flash” width=”400″ height=”220″  wmode=”transparent” data=”flvplayer.swf”>
<param name=”movie” value=”flvplayer.swf” />
<param name=”wmode” value=”transparent” />
<object/>

flvplayer.swf会自动找到同一目录内的video.flv播放。也可以在flvplayer.swf后添加FLV文件的URL来进行播放。方法如下:

程序代码
<object type=”application/x-shockwave-flash” width=”400″ height=”220″ wmode=”transparent” data=”flvplayer.swf?file=movies/holiday.flv”>
<param name=”movie” value=”flvplayer.swf?file=movies/holiday.flv” />
<param name=”wmode” value=”transparent” />
</object>

file=movies/holiday.flv就是参数,可以使用相对或者绝对地址。

其他参数说明:如果载入影片时不需要自动播放,可以使用autostart参数

例子
<object type=”application/x-shockwave-flash” width=”400″ height=”220″
wmode=”transparent” data=”flvplayer.swf?autostart=false”>
<param name=”movie” value=”flvplayer.swf?autostart=false” />
<param name=”wmode” value=”transparent” />
</object>

三月 31, 2011

页面输出缓存(页面静态化)的设计

Filed under: 乱7八糟 — admin @ 9:37 上午

随着网站规模的变大,访问量提升,网站服务器越来越不堪重负,浏览者也会对页面打开的速度怨声载道。
这时候最简单的解决方案就是增加缓存。
网站服务器的缓存有很多中,可以放在数据库和Web应用程序之间,也可以放在Web应用程序和Web服务器之间,还可以放在Web服务器和用户浏览器之间,甚至可以直接放在浏览器端。
其中最简单,需要配置最少的莫过于数据库和Web应用程序之间了,并且见效也最快,因为对于现代计算机系统来说IO是最大的瓶颈。常见的方法就是使用MemCache或者K-V型NoSQL数据库做缓存。
这么安逸了一段时间之后,网站的响应速度还是会降下来,如果你不想增加服务器的话,这时需要做的就是页面输出缓存了。
因为数据库和Web应用程序端的缓存只是将数据库中的键和值缓存下来,访问量大的话有一个命中率的问题,并且一个页面往往包含有大量的需要从数据库查询的值,就算数据库缓存全部命中,这其中也需要一个查询的过程,即时它很快。还有一个问题,就是对于Web应用程序来说,从获取数据到输出页面,中间还需要一些逻辑性运算和模板的渲染过程,这个过程也会消耗一段时间。
如果将一个页面响应的结果,也就是HTML页面,整体缓存下来,Web服务器直接输出缓存结果,这样的速度基本上相当于直接输出静态页面,对于服务器端的负载将会大大减轻。
对于页面输出缓存,或者有人称之为页面静态化,主要有以下几个问题:

页面个性化部分的处理。现在绝大部分网站都有登录给功能,对于同一个页面来说登录前后、不同用户登录后都会有不同的显示,比如说未登录时显示“登录或注册”,登录之后显示“欢迎用户XXX”,这样就会造成网站大部分页面都不能直接缓存。
其实这个问题是在页面个性化部分与非个性化部分合成的时间问题上。传统网站这个个性化部分也非个性化部分是直接放在Web应用程序上的,这样就导致不同用户输出页面的不同,缓存不能进行。如果把这个过程放在页面缓存程序之后,使缓存的结果相同就没有问题了。
常见的方式就是使用SSI、ESI和CSI。
SSI(Server Side Include)这个现在大部分的Web服务器都支持,可以在页面中使用<!–#include file=”/user_info.shtml”–>来替代原来个性化的部分,然后在Web服务器上就会去寻找这个.shtml文件,将它与页面合成。不过这有一个问题,ssi只能将静态文件与页面合成,这样对于做页面输出缓存意义并不大。
ESI(Edge Side Include)正是为了应付这种场合而出现的,它可以使用类似<esi:include src=”http://example.com/1.html” alt=”http://bak.example.com/2.html” onerror=”continue”/>的XML语法,在页面合成过程中调用一个动态页面,将动态页面的内容与现有网页合成。这样一来就可以将某个用户的个性化信息与缓存的页面文件合成了。ESI最大的问题就是现有Web服务器对此支持度不高。Nginx需要将第三方模块编译进来来支持ESI,代理缓存服务器中Varnish原生支持ESI。
CSI(Client Side Include)或者叫做Browser Side Include,就是在用户浏览器端将个性化信息与非个性化信息合成。说白了就是用ajax异步获取个性化信息,或者直接使用iframe显示个性化信息。实际上这个合成的过程越靠近用户浏览器端越好,这样就可以一直从Web服务器到代理服务器的缓存到CDN都可以用到这些完全相同的页面做缓存。但是使用ajax等方式有一些问题,就是对于不支持或者不开启的JavaScript的浏览器来说就不能正常访问页面了,现在很多网站都要考虑到手机客户端,其中不支持JavaScript的占大多数。并且大量使用ajax的话对用户浏览器来说也是一种负担,并且会造成页面加载很“卡顿”的感觉。
具体的做法还是依赖实际环境来决定。

剩下需要解决的方式是如何来缓存页面。
使用代理缓存服务器是一个比较不错的主意,比如Squid还有比较新的Varnish,它们都可以架设在Web服务器前端作为代理缓存服务器,将页面缓存下来。当页面需要更新的时候可以给它发送一个Purge请求加具体页面URL,就可以使代理缓存服务器去访问Web服务器,重新生成一个新的页面,然后将现有的页面缓存失效。这个过程中当新的用户访问请求达到时,代理缓存服务器还是使用之前的缓存,新的缓存页面生成结束后才使过期的页面失效。这样就不用担心更新缓存过程中所有用户请求都去直接访问Web服务器造成大量的压力了。这其中有一个问题,就是触发这个更新动作的用户,比如说他发布了一条回复造成页面更新,如果页面更新请求与页面缓存更新两个动作是异步的话,假如他的网速足够快就会看到自己刚才发布的帖子没有显示出来,造成重复发帖等动作。这个问题接下来再来想办法处理。
如果不想另外搞一个代理服务器的话,Nginx的fastcgi cache是一个好东西,可以直接将fastcgi的页面缓存下来。配合一个第三方的模块cache purge,可以通过访问/purge/url的方式来时缓存过期。另外Nginx+proxy cache+cache purge也可以达到上面Squid和Varnish的作用。
剩下还有一种方式,使用Nginx的rewrite,将缓存保存为一个静态文件,先检查静态页面是否存在,存在的话rewrite到此,不存在则访问Web应用程序。这样还需要另外配合一个独立的进程,来生成缓存页面。当Web应用程序触发更新时给此进程发送一个信号,缓存进程收到此信号后去Web服务器端或者Web应用程序端请求页面(为了做到松耦合和以后的服务器分离最好直接从Web服务器端),将请求生成的页面文件直接覆盖远缓存的静态文件,这样就可以更新缓存,并且在缓存更新过程中访问者依然可以使用之前的缓存文件。

还有一个问题,当很多用户在同一个时间点内同时触发一个页面的更新动作,这样就会导致此页面频繁更新,并且这些更新是不必要的,这就是所谓的惊群问题。
防止此事件发生,一个解决方案是使用队列。
一般页面发生内容变化是在提交POST请求之后,在此时给缓存更新系统发送一条消息,记录发生更新动作的类型、ID(比如说帖子更新,更新的ID)。缓存更新系统在接受到此消息时将消息进行预处理,根据配置文件计算出影响更新的页面(此帖子的页面,帖子列表的页面,等等)。
将此页面的URL插入进队列,更新程序在队列另一端取URL,每取一次URL就过滤一遍整个队列,将相同的URL队列消息删除出队列。这样就可以保证更新依次页面,就可以相应所有更新事件。取出后依据使用的缓存系统发送相应的Purge请求或者自主生成新的缓存页面覆盖老的野蛮来更新缓存。
这种去重复的队列实现可以用现有的模块,比如Python的一个Queue模块,继承此模块中的类并重写几个方法即可实现这种去重的队列。还可以使用现有的队列系统,甚至直接使用数据库来实现队列。使用数据库有一个好处,就是当整个系统Down掉的时候,系统重启后队列中的消息还存在,可以继续更新这些页面的缓存。如果直接使用内存中的队列的话系统Down掉重启就会导致一些未处理的队列消息丢失,导致这些页面的缓存都没有更新。这种情况出现的几率还有出现后对系统的影响需要根据实际情况斟酌,论坛系统如果发帖不是十分频繁,偶尔某个帖子或者回复没有出现并不是非常严重的问题。

一个好的系统应该是针对发生故障的情况而设计的。假如缓存系统出现问题,导致没有向缓存服务器发送更新请求,这时所有更新动作都不会得到相应,导致用户重复提交数据,可能会发生一些问题。这时如果能停掉缓存服务器,让用户直接访问Web应用程序或许是一个好主意(或者如果没有缓存的话服务器能被直接大量直接访问干掉),如果去做是一个问题。
Some Tips:
上面说的如果异步处理更新动作与缓存更新的话,可能会使更新触发者看不到自己更新的数据。这时可以使用一些小花招,比如现在大部分的论坛系统在发帖后跳转到一个“3秒后跳转到帖子页面”,就可以给缓存系统提供充分的更新缓存时间,对于用户体验来说也不会大打折扣。
有些页面不能使用缓存,比如说帖子列表页面。因为帖子列表页面是会随着最后回复时间来动态更新排列顺序的,一个新帖或者回复可能会导致所有帖子列表分页内容发生变化,而帖子列表分页可能有几千甚至几万页,全部都进行更新的话显然是不可能也没有必要的。因此这些页面不适用页面输出缓存,但我们可以只缓存帖子列表的第一页或者前几页,因为绝大部分的访问请求都是来自与这几个页面,每次更新动作都触发这几个页面进行缓存更新也是没有问题的。
假如网站每日发新帖的数量非常高,导致帖子列表更新十分频繁,这时可以使用另外一种更新触发机制,就是按时间来触发更新。这样定时更新的频率比之前按动作进行更新会少一些,并且也不会过分加重队列的负担。
网站首页的信息可能会比较复杂,触发其更新的来源可能会很多,更新一次的成本也较高,而首页对于事实性的要求也没有那么高(比如说在某个板块发布新贴,这时在首页的最新帖子列表中没有看到此贴,对于绝大部分用户来说并不是什么问题),因此也试用于按时间进行更新的机制,并且这个更新时间的间隔可以适当的拉长一些。
类似的还有帖子回复页,此页面也是一个列表排序页面,但是是顺序时间排列的(帖子列表为倒序时间排列的),因此也十分适用与使用缓存。如果网站当初设计的功能为显示所有楼层,删除某一楼层的话此位置消失,这样的话如果删除一个楼层将会导致此页面和接下来所有页面的内容发生变化。因此在网站设计时最好设计成这样:删除一条回复,此回复还在,只不过内容改为了“评论已删除”,这样就不会触发所有后来页面进行缓存更新了。

三月 25, 2011

upstream timed out (110: Connection timed out) while reading response header from upstream

Filed under: linux — admin @ 10:23 上午

nginx 老报错 百度搜索了下  发现了下面的文章 不过说实话我还没去试 哈哈

系统版本 CENTOS 5.5 NGINX PHP

在错误日志里看到几百个 upstream timed out 的错误.

2010/12/15 22:32:45 [error] 3897#0: *1831129 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 116.217.163.37, server: xxx.com.cn, request: “GET / HTTP/1.1″, upstream: “fastcgi://127.0.0.1:9000″, host: “xxx.com.cn”, referrer: “http://xxx.com.cn/”

以下的文章是转载的 但其实我的解决办法是关闭iptables 就好了

service iptables stop 就OK了 具体问题我也很郁闷 我并没有封闭9000端口 不过确实就这样好啦

从日志的表示来看应该不是nginx的问题,而是 fast-cgi 执行超时没有及时返回数据到ngnix的问题. 可web和数据库负载都不高,不应该是

程序超时的问题. 查资料也没有找到原因,网上于几个人说遇到同样问题,也没有好的解决方案. 后来仔细分析日志,发现出现错误的日志的时间都是大于当前时间,这点很奇怪,难道是系统时间的问题? 后来再仔细查资料,才找到原因. 原来是 centos 的一个内核bug, 调用gettimeofday()这个函数的时候会比当前时间快4398秒.  具体原因是因为多核cpu,各核的TSC不一样造成的.  看来 fast-cgi 应该是调用了这个函数的.

解决方案是升级内核..  相信很多和我一样不是专业sa的兄弟对升级内核之类的事情还是比较犯怵的,不过不用担心有一个不用升级内核的解决方案. 在不升级kernel的情况下,可以考虑修改time source,来解决。修改kernel option。

具体操作如下:

vim /etc/grub.conf

kernel /vmlinuz-2.6.9-1.667 ro root=/dev/hda2 clock=pit (红色部分为新增的)

然后重启服务器,问题解决.  我的产品环境已经3天没有报这个错误了.

三月 20, 2011

shell 日志切片小脚本

Filed under: linux — admin @ 8:00 下午

接上文 从ROS 接收到日志了以后 进行切片

#!/bin/bash
LOG=/var/log/ros/ros.log
if [ `wc -l $LOG |awk '{print $1}'` -gt 3000000 ]
then
  split -l 900000 ros.log os
  cat /dev/null >$LOG
  exit 1
fi
将日志按行数切割啦

linux syslog 接收route ros日志

Filed under: linux — admin @ 4:54 下午

配置LINUX SYSLOG

先看下服务器安装SYSLOG包了没

rpm -qa |grep syslog

编辑vi /etc/sysconfig/syslog
SYSLOGD_OPTIONS=”-r -x -m 0″ 加R的意思是接收任何外部来的日志

如何发送日志你们就自己研究下ROS吧

接下来的是如何吧接收来的日志和MESSAGE分离 要不乱7八遭

vi /etc/syslog.conf
# 把emerg等级的消息从messages中除开,免得重复记录:
*.info;*.!emerg;mail.none;authpriv.none;cron.none /var/log/messages          # *.!emerg 表示不记录emerg级的消息
#*.emerg    *                   # 注释掉原来的emerg,不将emerg级消息显示到控制台
# 输出到/var/log/mylog
*.emerg  /var/log/mylog

然后重启syslog:service syslog restart

这样就把远程日志写入/var/log/syslog并且不影响本机syslog工作了

下面是如何获取到得日志写入到MYSQL里面 在PHP读取出来 哈哈 未完待续啦。。。。。

三月 14, 2011

sed 替换指定某行

Filed under: linux — admin @ 4:39 下午

-i 是开关 直接替换。不用输出到内存

test 里面内同为linuxqq=abc 我需要替换成linuxqq=123

sed -i ‘s/linuxqq=abc/linuxqq=123/g’ test

sed -i ’1,10s/linuxqq=abc/linuxqq=123/g’ test  匹配1-10行的范围

就OK啦~·

三月 13, 2011

dlink dir 365 双无线路由

Filed under: 乱7八糟 — admin @ 4:01 下午

  买了2个无线路由 型号是DLINK DIR 365 均有无线功能

2个路由分别简称A,B

一根ADSL接入,B路由接到A路由上。

A:192.168.0.*

B:192.168.1.*

配置好后 1楼用A路由上网 2楼用B路由上网 均正常。但是问题就出在需要共享一个打印机,现在只有A路由网段可以使用打印机,B路由网段无法使用,跨网段了。

发现DLINK DIR 365 没有无线网桥功能 郁闷呐。。寻找了半天 发现可以做路由策略 在B路由上设置 凡是目的地192.168.0.*的包 都通过192.168.1.1的WAN口出去 OK了 就这样正常了 说白了做了一个NAT 。实现了无线功能打印

转载注明(LINUXQQ)

在高级里面 找到路由功能

« Newer PostsOlder Posts »

Powered by LINUXQQ   ICP 10203065