关于对浏览器兼容性的一点点理解

原来对浏览器兼容性的理解主要是:

1. 要对浏览器兼容性做判断
2. 不是所有浏览器都支持的东西尽量不要用

今天看了QQ空间的一点代码,有所启发:
1. 要善于利用浏览器的一些特性;比如,现在的主流浏览器是IE和FF,IE中有很多功能是FF中所没有的,如果用js来实现这些功能可能是很大一段的js;按照原来的想法就是不去使用IE的那个功能,统一使用js来实现,这样自然没有兼容性问题。但是今天的想法却是: 在IE中就是用IE提供的功能,只有在FF中才通过js来实现; 这样做的好处就是,对于大部分的用户不需要下载那一大段的js了,对用户和服务器都是有好处的。有些功能是FF中有的,IE中没有,我们也可以这么来做。

2. 下面给出一段QQ空间的代码:http://b.cnc.qzone.qq.com/proxy.html

<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><SCRIPT>
document.domain = "qq.com";var b=false;
if (window.execScript)try{execScript("b=Asc(‘啊’)=-20319","vbscript");
}catch(e){status = "系统vbscript引擎可能已经被损坏或者反注册。尝试运行 regsvr32 vbscript.dll 命令有可能解决此问题";
}
if(!b){
document.write("<script language=’javascript’ src=’http://imgcache.qq.com/qzone/client/js/gbk.js’><\/script>");
}else{
document.write("<script language=’vbscript’ src=’http://imgcache.qq.com/qzone/proxy.vbs’><\/script>");
String.prototype.GBEncode=function(){return URLEncoding(this)}
}
</SCRIPT><script src="http://imgcache.qq.com/qzone/proxy.js"></SCRIPT><script>
if (typeof proxyLoaded=="undefined"){
document.createElement("SCRIPT").src="http://imgcache.qq.com/qzone/proxy.js?"+Math.random();
alert("proxy脚本无法正常下载,可能与您当地的网络状况有关系。\n请您关闭浏览器,重新打开空间进行尝试。");
}
</script>
</head></html>

怎样在Apache2下开启gzip压缩

原来听说使用script标签动态加载js时,加载源不能做gzip压缩,今天测试了一下,没这回事儿,不管ff和ie都没有这回事儿。
顺便了解了一下怎样在Apache2下开启gzip压缩。

        

  1. # 加载deflate模块
  2.     

  3. LoadModule deflate_module modules/mod_deflate.so
  4.     

  5. # 设置压缩频率,取值范围在 1(最低压缩率) 到 9(最高压缩率)之间
  6.     

  7. # 不建议设置太高,虽然有很高的压缩率,但是占用更多的CPU资源
  8.     

  9. DeflateCompressionLevel 3
  10.     

  11. # Compress everything except images
  12.     

  13. <Location />
  14.     

  15. # 插入过滤器
  16.     

  17. SetOutputFilter DEFLATE
  18.     

  19.  
  20.     

  21. # Netscape 4.x 有一些问题…
  22.     

  23. BrowserMatch ^Mozilla/4 gzip-only-text/html
  24.     

  25. # Netscape 4.06-4.08 有更多的问题
  26.     

  27. BrowserMatch ^Mozilla/4\.0[678] no-gzip
  28.     

  29. # MSIE 会伪装成 Netscape ,但是事实上它没有问题
  30.     

  31. BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  32.     

  33. # 不压缩图片
  34.     

  35. SetEnvIfNoCase Request_URI \\.(?:gif|jpe?g|png)$ no-gzip dont-vary
  36.     

  37. </Location>

利用httpwatch做web自动化测试和分析

httpwatch 是个不错的东西,它是web开发者的一把利器;另一把利器就是Firebug 。
关于httpwatch自动化测试和分析的例子详见httpwatch的帮助文档之:
Automating HttpWatch

另外, 如果你有visual studio的话,可以在对象浏览器中选择“编辑自定义组件集”,添加httpwatch的com组件,这样查看httpwatch的api更加方便一些。非常推荐的哦

svn 命令行实例

关于命令行svn的学习:

检出: 需要 url 用户名 密码  
注意url中的地址不能写根目录,checkout使用的http header里的方法也是很特殊的
D:\svn_test\test2>svn checkout "https://localhost:8443/svn/test2/" –username svnuser –password lijunjie ./

更新

svn update

添加
svn add

删除
svn delete

提交
svn commit -m “提交的注释”

使用vim编辑注释
svn commit –editor-cmd vim

比较
svn diff
和上一个版本比较
svn diff -r PREV

关于svnserve服务器的配置,参考svn-book.pdf

1. 安装 (略)
2. 配置/etc/svnserve.conf
    #content , detail reference svn-book.pdf
    [general]
    password-db = /etc/svnserve.pass
    realm = example realm

    # annonymous users can only read the repository
    anon-access = read

    # authenticated users can both read and write
    aut-access = write

3. 配置权限文件 /etc/svnserve.pass
    [users]
    junjie = junjie

4. 创建版本库
    svnadmin create /var/svnroot/test1

5. 启动
    svnserve -d -r /var/svnroot/ –config-file /etc/svnserve.conf

6. checkout
    svn checkout "svn://phpor.net/test1"
    svn checkout –non-interactive –username lijunji –password xxxx "https://phpor.net/" ./

7. 比较
    svn diff -r 4974:17599 getst.php

8. 移动
    svn move –force a b\
9. 提交
    svn commit -m "comment for move "
10. merge
如: branches\branche1  是 trunk的一个分支,当truck有修改后,假设从版本11升到版本12,要想将版本11到版本12的修改在branche1里也
体现出来,则可以使用merge命令,即:
    svn merge -r 11:12 trunk branches\branche1
    这时branche1里面的文件也做了相应的修改,只是我们还需要人工确认一次,确认修改的没有问题后,再提交一次
    svn commit -m "merge from trunk"
    这时,相应的修改在分支里面体现为版本13,就是说分支里永远找不到版本12的修改
   
    merge 的实质是diff and apply

11. 查看log
svn log –limit 3  -v

–limit n  查看最近n条更新
-v  显示修改的详细信息
-r  指定要查看的版本号,也可以指定日期

svn log -r{2009-05-10}:{2009-06-10}  -v

在服务器上使用svn命令时总出现乱码,处理办法,使用icovn做转码:
svn log -r 4472 |iconv –from utf-8 –to gb2312

PHP 模块编写需要注意的一个问题—- php模块及函数名都定义成小写吧

   这是一个困扰我很长时间的问题,曾经由于没有思路,一直搁置没有去追究,现在要对该模块做一些修改,就想顺便把这个问题给查明白了,事情是这样的…

我们写了一个PHP模块String2Hash,其实里面只有一个函数叫: String2Hash() ,只是要将一个字符串hash成一个整数,由于PHP中的整型都是有符号的,该算法涉及移位,求和,求模,等操作,用PHP实现比较麻烦,就用C写了一个PHP的模块。
编译完之后,执行:
php –re String2Hash
就报错如下:
PHP Warning:  Internal error: Cannot find extension function String2
Hash in global function table in Unknown on line 0

虽然有警告,但是该模块时可以正常加载和使用的; 一般来讲,程序员只关心error,不关心Warning的,但是我就想知道个究竟。

第一步: 先做一个helloworld模块,这个完全是生成的,只有很少的修改,结果是没有报错的。
第二步: 将自己的函数添加进去,开始报错。
第三步: 将自己的函数重命名为myhash, 编译不再报错。问题基本出现在函数名上了。可能是大小写的问题吧?突然想到报错提示,可能是
global function table这个数组的key是区分大小写的?
第四步: 将String2Hash 重命名为string2hash, 为了保险,将所有出现的地方都改成小写吧,反正PHP函数是不区分大小写的,改成小写也无妨。 编译不再报错,测试通过,问题解决

have fun!!!

c代码翻译为PHP时遇到的问题

最近由于想把下面这段c代码翻译为PHP的,未能成功:

unsigned long myhash(const char *s, long mod){
unsigned char ch;
unsigned int h = 5381;
int len = strlen(s);
while (
len > 0)    {
ch = *s++ - 'A';
if (
ch <= 'Z' - 'A'){
ch += 'a' - 'A';
}
h = ((h << 5) + h) ^ ch;
--
len;
}
return
h%mod;
}

遇到的问题是:

1. PHP 的整型总是有符号的
2. PHP 的整型在32位机上是32位的,在64位机上是64位的

期望能通过pack,unpack函数来实现,研究了半天,也没有实现。

还想搞清楚的问题:

一个负数 a 模上一个数 M, 和将a强制转换成无符号后模上相同的M,其结果之间是什么关系?
如:
-100 % 15  = -10;
((unsigned) (-100)) % 15 = 6

[root@login ~]# php -r "echo sprintf('%u',-100);"
4294967196

然后用bc算一下就知道了

关于gethostname系统调用

关于hostname的事情,我不知道是存放在系统的什么地方的,想知道时却发现是通过系统调用gethostname实现的,给系统调用在linux上只要包含<unistd.h>,就可以使用;
但是在windows上就没有在这个里面,windows上我没有使用visual studio,而是下载了一个dev-c++;因为对于命令行的东西比较熟悉一些,同样的程序在linux上是没问题的,但是在windows上就是编译不过去;
代码如下:
#include <unistd.h>
#include <iostream>

using namespace std;

int main(int ac, char ** av) {
    char name[256];
    size_t len = 256;
    gethostname(name, len);
    cout << name << endl;
    return 0;
}

在windows上需要添加:

#include <winsock2.h>

而在编译时也需要把libwsock32.a 带上,如:
g++ -L D:\Program\DEV-CPP\Lib  -o gethostname gethostname.cpp 
D:\Program\DEV-CPP\Lib\libwsock32.a

你可能会问,为什么已经使用了-L了libwsock32.a还要使用全路径,这个我也不知道,反正不给全路径就是找不到该文件。

虽然windows上也编译成功了,但是输出的结果却不是hostname命令所看到的,难道是这个libwsock32.a里面的gethostname的实现和hostname命令不太一样?通过denpendency woker这个小软件查了一下,使用的是同一个dll中的系统调用。 为什么结果不一样就不知道了,windows上的东西就是不好查。

apache 的AcceptMutex 的理解

当apache监听多个端口或多个ip上的端口时,多个子进程是怎么分工的呢?和只监听一个端口有什么区别吗?

1. 如果apache的多个进程只监听一个端口,则不需要AcceptMutex,每个apache进程都在执行accept操作,发现请求后就开始执行,执行完继续accept,多个进程之间不会相互干扰,这是由accept的机制来完成的。

2. 如果apache的多个进程只监听socket多于一个,则不能直接accept了,就必须使用select或poll机制来发现知否有请求需要执行,发现之后,再由accept来接受请求;然而select或poll没有accept那么能自动处理互斥的问题,这时候就需要一个“锁”了,就是所谓的AcceptMutex,AcceptMutex的实现形式有多种,这个不属于本文讨论的范围。
   下面是apache在监听三个socket(
[16 17 18])时,其中一个进程的表现:
semop(524288, 0x81dd334, 1)             = 0
select(19, [16 17 18], NULL, NULL, NULL) = 1 (in [17])
accept(17, {sa_family=AF_INET, sin_port=htons(52932), sin_addr=inet_addr("10.55.38.9")}, [16]) = 29
semop(524288, 0x81dd33a, 1)             = 0

第一步:先获取锁(0x81dd334), 同一时刻只有一个进程能获取锁
第二步:开始select(对于apache2这里好像是poll,poll的效率更高一些),并且发现17需要处理了
第三步:accept 17
第四步:释放锁,这样其它进程就可以获取锁并处理后续的请求了

配置ZendServer时遇到的问题及解决办法

关于ZendServer请访问官方网站: http://www.zend.com/en/

问题一: 安装后访问PHP文件总是“内部服务器错误”
解决办法:
查看apache的错误日志发现是文件ZendEnablerConf.xml解析失败,打开发现第一行乱码,修改就行了。

问题二: 重新配置了一下httpd.conf,添加了两个虚机;但是启动总是提示:
httpd.exe: Could not reliably determine the server’s fully qualified domain
解决办法:
在虚机外面添加一个ServerName就行了,写127.0.0.1就行;可以通过命令
httpd.exe   -t
检查出来的。
因为如果没有ServerName,则将通过 ap_get_local_host 来发现ServerName, 发现了的ServerName和 hostname命令看到的是一样的,但是发现后还要判断有效性和反解析的。如果ServerName中没有“.” 就不合法,如果反解析出来不正确也不行。
所以,这里要注意两个问题:
1. 要么在每一个虚机外面设置一个ServerName, 要么hostname设置要合法且有效
2. windows上的hostname里面是不能含有”.“的;
如:

$hostname
phpor.cn


hosts 文件如下就可以:

127.0.0.1       phpor.cn
127.0.0.1       localhost


hosts 文件如下就不可以:

127.0.0.1       phpor.cn
127.0.0.1       localhost


问题三: 这个是我一个手误,把虚机配错了,总是进入不到想要的虚机
解决办法:
我只想知道我的请求到底进入了哪个虚机,怎么办?可以在不同的虚机里面使用Header指令给响应头添加标识就行了,如:
Header set vhost phpor.net
这样查看响应头就知道是进入了哪个虚机了