在配置多个SSL的虚拟主机的时候,很容易想当然的像配置普通HTTP虚拟主机一样,新建一个Virtualhost后reload服务器。可用浏览器访问的时候,却提示证书为已经存在的某个虚拟主机的SSL证书,造成配置失败。
网上查询得知,一个普通的SSL证书是独占服务器端口。也就是说,如果Apache服务器上的虚拟主机A使用了SSL_A,并监听端口443,那即使新配置了虚拟主机B,如果虚拟主机是按照配置的,那用户访问时候读取的仍然是SSL_A。这和普通虚拟空间可以通过设置域名来区别虚拟主机是不同的。
要解决这个问题,实现一个Apache服务器上提供多个SSL虚拟主机,可以:
使用多域名SSL证书,可以实现一个IP,一个443端口上多个SSL虚拟主机;
为所有SSL虚拟主机配置单独的端口。比如,默认的虚拟主机使用443,其他的使用8080或8081等,且每个SSL虚拟主机必须独占一个端口;
为Apache服务器配置多个IP,每个SSL虚拟主机独占IP。如果只有一张物理网卡,可以配置为网卡配置子接口;
使用mod_gnutls模块,创建多个SSL虚拟主机
总之,Apache的SSL虚拟主机配置需要保证每个SSL虚拟主机有独立的IP:Port组合,如果不能提供这个条件,那只好多域名SSL证书了。
网上查询得知,一个普通的SSL证书是独占服务器端口。也就是说,如果Apache服务器上的虚拟主机A使用了SSL_A,并监听端口443,那即使新配置了虚拟主机B,如果虚拟主机是按照配置的,那用户访问时候读取的仍然是SSL_A。这和普通虚拟空间可以通过设置域名来区别虚拟主机是不同的。
要解决这个问题,实现一个Apache服务器上提供多个SSL虚拟主机,可以:
使用多域名SSL证书,可以实现一个IP,一个443端口上多个SSL虚拟主机;
为所有SSL虚拟主机配置单独的端口。比如,默认的虚拟主机使用443,其他的使用8080或8081等,且每个SSL虚拟主机必须独占一个端口;
为Apache服务器配置多个IP,每个SSL虚拟主机独占IP。如果只有一张物理网卡,可以配置为网卡配置子接口;
使用mod_gnutls模块,创建多个SSL虚拟主机
总之,Apache的SSL虚拟主机配置需要保证每个SSL虚拟主机有独立的IP:Port组合,如果不能提供这个条件,那只好多域名SSL证书了。
MySQL环境变量设置,将%MySQL_HOME%下的MySQL Server 5.1\bin放到Path下。
MySQL的mysqldump工具,基本用法是:
shell> mysqldump [OPTIONS] database [tables]
通过执行mysqldump --help,得到当前mysqldump版本支持的选项表。
通过执行mysqldump –V,得到当前mysqldump版本。
几个常用的例子(在mysqldump Ver 10.13 Distrib 5.1.30, for Win32 (ia32)下测试通过)
1.导出整个数据库
mysqldump -u 用户名 -p 数据库名 > 导出的文件名
mysqldump -u root -p student >d:\student.sql
2.导出一个数据库结构
mysqldump -u root -p -d --add-drop-table student >d:\student_structure.sql
-d 没有数据 --add-drop-table 在每个create语句之前增加一个drop table
3.导出一个表
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
mysqldump -u root -p schoolproject student>d:\schoolproject_student.sql
4.导入数据库
shell> mysqladmin –u root –p create target_db_name
shell> mysql –u root –p target_db_name < backup-file.sql
就是:shell> mysql 数据库名 < 文件名
或者使用source 命令
进入mysql数据库控制台,mysql -u root –p
mysql>use 数据库
然后使用source命令,后面参数为脚本文件(.sql文件)
mysql>source d:\student.sql
MySQL的mysqldump工具,基本用法是:
shell> mysqldump [OPTIONS] database [tables]
通过执行mysqldump --help,得到当前mysqldump版本支持的选项表。
通过执行mysqldump –V,得到当前mysqldump版本。
几个常用的例子(在mysqldump Ver 10.13 Distrib 5.1.30, for Win32 (ia32)下测试通过)
1.导出整个数据库
mysqldump -u 用户名 -p 数据库名 > 导出的文件名
mysqldump -u root -p student >d:\student.sql
2.导出一个数据库结构
mysqldump -u root -p -d --add-drop-table student >d:\student_structure.sql
-d 没有数据 --add-drop-table 在每个create语句之前增加一个drop table
3.导出一个表
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
mysqldump -u root -p schoolproject student>d:\schoolproject_student.sql
4.导入数据库
shell> mysqladmin –u root –p create target_db_name
shell> mysql –u root –p target_db_name < backup-file.sql
就是:shell> mysql 数据库名 < 文件名
或者使用source 命令
进入mysql数据库控制台,mysql -u root –p
mysql>use 数据库
然后使用source命令,后面参数为脚本文件(.sql文件)
mysql>source d:\student.sql
Ubuntu是一套基于Debian的Linux系统,它追求的是“Just Work”,最新的7.10版本发布于2007年10月,不同于其他Linux发行版本,Ubuntu的所有版本都是免费的,包括企业版。
第一次安装Ubuntu,发现比较“奇怪”的一点是,在安装过程中,不像其他发布版本那样,要求设置root的密码,也就无法以root登录了。经过去网上查询才发现:Ubuntu默认是关闭root帐户的,这样做有如下优点:
起初Ubuntu团队希望安装尽可能的简单,不使用root,在安装期间的两个用户交互步骤可以省略。(科林·沃森)
更进一步, 如果在安装中使用root,用户将被要求永远记住他们选择的密码--即使他们很少使用到它。Root密码经常被对Unix安全模型不熟悉的用户忘记。(马特·齐默曼)
它防止了缺省登录时“我能做任何事情”--在较大的变化发生之前,你将被提示输入口令,这可以使你考虑你这样做的结果。 如果你作为root登录,你可以删除一些“没用的文件夹”并且不会意识到你正处于错误的目录,那时已经太晚了。它是在Unix下长时间使用“su-command-^D”练习的情况下,代替一直呆在root shell--除非你做严重的系统维护(那时你仍然可以使用 "sudo su")。(吉姆·奇塔姆 和 安德鲁·索巴拉)
Sudo 增加了运行命令的日志记录(在/var/log/auth.log)。如果你陷入困境,你总是可以返回并看见那些运行的命令。(安德鲁·Zbikowski)
开启root帐号的方法:
为了启用root 帐号(也就是设置一个口令)使用:
sudo passwd root
当你使用完毕后屏蔽root帐号使用:
sudo passwd -l root
这个将锁住root帐号。
如何在终端模式下切换到root身份?
sudo -s -H
Password: <在此输入密码>
allen:用root帐户怎么也登陆不了。原来默认是关闭的。汗一个...-_-!! 帐户已经启用 哈哈YES
第一次安装Ubuntu,发现比较“奇怪”的一点是,在安装过程中,不像其他发布版本那样,要求设置root的密码,也就无法以root登录了。经过去网上查询才发现:Ubuntu默认是关闭root帐户的,这样做有如下优点:
起初Ubuntu团队希望安装尽可能的简单,不使用root,在安装期间的两个用户交互步骤可以省略。(科林·沃森)
更进一步, 如果在安装中使用root,用户将被要求永远记住他们选择的密码--即使他们很少使用到它。Root密码经常被对Unix安全模型不熟悉的用户忘记。(马特·齐默曼)
它防止了缺省登录时“我能做任何事情”--在较大的变化发生之前,你将被提示输入口令,这可以使你考虑你这样做的结果。 如果你作为root登录,你可以删除一些“没用的文件夹”并且不会意识到你正处于错误的目录,那时已经太晚了。它是在Unix下长时间使用“su-command-^D”练习的情况下,代替一直呆在root shell--除非你做严重的系统维护(那时你仍然可以使用 "sudo su")。(吉姆·奇塔姆 和 安德鲁·索巴拉)
Sudo 增加了运行命令的日志记录(在/var/log/auth.log)。如果你陷入困境,你总是可以返回并看见那些运行的命令。(安德鲁·Zbikowski)
开启root帐号的方法:
为了启用root 帐号(也就是设置一个口令)使用:
sudo passwd root
当你使用完毕后屏蔽root帐号使用:
sudo passwd -l root
这个将锁住root帐号。
如何在终端模式下切换到root身份?
sudo -s -H
Password: <在此输入密码>
allen:用root帐户怎么也登陆不了。原来默认是关闭的。汗一个...-_-!! 帐户已经启用 哈哈YES
一、简介
如果你对Unix/Linux有所了解的话,你应该知道他们大都自带了C和C++的编译器,分别是GCC和G++。Unix在程序安装及Make等许多地方使用到了这些编译器。利用一些控制台命令,C++和PHP, 我将向你介绍怎样生成一个完整的C++程序例子,他可以在用PHP程序来执行,并能获得相应的输出结果。我将先生成C++程序代码,并编译它,谈后讨论我们将如果通过使用PHP的函数passthru来执行这个程序。从某种意义上来说,这边文章给我们提供一种通过Web页面来访问一般程序的方法。
为了能更好的理解这篇文章,你应该有一台运行着apache和最新版本php的unix/Linux服务器。同时也应该掌握C++, unix控制台命令,当然一些PHP的编程经验也是必需的。
二、编写一个C++程序阅读全文
如果你对Unix/Linux有所了解的话,你应该知道他们大都自带了C和C++的编译器,分别是GCC和G++。Unix在程序安装及Make等许多地方使用到了这些编译器。利用一些控制台命令,C++和PHP, 我将向你介绍怎样生成一个完整的C++程序例子,他可以在用PHP程序来执行,并能获得相应的输出结果。我将先生成C++程序代码,并编译它,谈后讨论我们将如果通过使用PHP的函数passthru来执行这个程序。从某种意义上来说,这边文章给我们提供一种通过Web页面来访问一般程序的方法。
为了能更好的理解这篇文章,你应该有一台运行着apache和最新版本php的unix/Linux服务器。同时也应该掌握C++, unix控制台命令,当然一些PHP的编程经验也是必需的。
二、编写一个C++程序阅读全文
同时在线访问量继续增大 对于1G内存的服务器明显感觉到吃力严重时甚至每天都会死机 或者时不时的服务器卡一下 这个问题曾经困扰了我半个多月MySQL使用是很具伸缩性的算法,因此你通常能用很少的内存运行或给MySQL更多的被存以得到更好的性能。
安装好mysql后,配制文件应该在/usr/local/mysql/share/mysql目录中,配制文件有几个,有my-huge.cnf my-medium.cnf my-large.cnf my-small.cnf,不同的流量的网站和不同配制的服务器环境,当然需要有不同的配制文件了。阅读全文
安装好mysql后,配制文件应该在/usr/local/mysql/share/mysql目录中,配制文件有几个,有my-huge.cnf my-medium.cnf my-large.cnf my-small.cnf,不同的流量的网站和不同配制的服务器环境,当然需要有不同的配制文件了。阅读全文
其他强制操作,优先操作如下:
mysql常用的hint
对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法。同样,在mysql里,也有类似的hint功能。下面介绍一些常用的。
强制索引 FORCE INDEX
SELECT * FROM TABLE1 FORCE INDEX (FIELD1) …
以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引。
忽略索引 IGNORE INDEX
SELECT * FROM TABLE1 IGNORE INDEX (FIELD1, FIELD2) …
在上面的SQL语句中,TABLE1表中FIELD1和FIELD2上的索引不被使用。
关闭查询缓冲 SQL_NO_CACHE
SELECT SQL_NO_CACHE field1, field2 FROM TABLE1;
有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次),这样就需要把缓冲关了,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它。
强制查询缓冲 SQL_CACHE
SELECT SQL_CALHE * FROM TABLE1;
如果在my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲。
优先操作 HIGH_PRIORITY
HIGH_PRIORITY可以使用在select和insert操作中,让MYSQL知道,这个操作优先进行。
SELECT HIGH_PRIORITY * FROM TABLE1;
滞后操作 LOW_PRIORITY
LOW_PRIORITY可以使用在insert和update操作中,让mysql知道,这个操作滞后。
update LOW_PRIORITY table1 set field1= where field1= …
延时插入 INSERT DELAYED
INSERT DELAYED INTO table1 set field1= …
INSERT DELAYED INTO,是客户端提交数据给MySQL,MySQL返回OK状态给客户端。而这是并不是已经将数据插入表,而是存储在内存里面等待排队。当mysql有空余时,再插入。另一个重要的好处是,来自许多客户端的插入被集中在一起,并被编写入一个块。这比执行许多独立的插入要快很多。坏处是,不能返回自动递增的ID,以及系统崩溃时,MySQL还没有来得及插入数据的话,这些数据将会丢失。
强制连接顺序 STRAIGHT_JOIN
SELECT TABLE1.FIELD1, TABLE2.FIELD2 FROM TABLE1 STRAIGHT_JOIN TABLE2 WHERE …
由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按TABLE1、TABLE2的顺序连接表。如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序。
强制使用临时表 SQL_BUFFER_RESULT
SELECT SQL_BUFFER_RESULT * FROM TABLE1 WHERE …
当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁(这样其它的SQL语句就可以对这些记录进行查询了),并且可以长时间地为客户端提供大记录集。
分组使用临时表 SQL_BIG_RESULT和SQL_SMALL_RESULT
SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM TABLE1 GROUP BY FIELD1;
一般用于分组或DISTINCT关键字,这个选项通知MySQL,如果有必要,就将查询结果放到临时表中,甚至在临时表中进行排序。SQL_SMALL_RESULT比起SQL_BIG_RESULT差不多,很少使用。
mysql常用的hint
对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法。同样,在mysql里,也有类似的hint功能。下面介绍一些常用的。
强制索引 FORCE INDEX
SELECT * FROM TABLE1 FORCE INDEX (FIELD1) …
以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引。
忽略索引 IGNORE INDEX
SELECT * FROM TABLE1 IGNORE INDEX (FIELD1, FIELD2) …
在上面的SQL语句中,TABLE1表中FIELD1和FIELD2上的索引不被使用。
关闭查询缓冲 SQL_NO_CACHE
SELECT SQL_NO_CACHE field1, field2 FROM TABLE1;
有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次),这样就需要把缓冲关了,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它。
强制查询缓冲 SQL_CACHE
SELECT SQL_CALHE * FROM TABLE1;
如果在my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲。
优先操作 HIGH_PRIORITY
HIGH_PRIORITY可以使用在select和insert操作中,让MYSQL知道,这个操作优先进行。
SELECT HIGH_PRIORITY * FROM TABLE1;
滞后操作 LOW_PRIORITY
LOW_PRIORITY可以使用在insert和update操作中,让mysql知道,这个操作滞后。
update LOW_PRIORITY table1 set field1= where field1= …
延时插入 INSERT DELAYED
INSERT DELAYED INTO table1 set field1= …
INSERT DELAYED INTO,是客户端提交数据给MySQL,MySQL返回OK状态给客户端。而这是并不是已经将数据插入表,而是存储在内存里面等待排队。当mysql有空余时,再插入。另一个重要的好处是,来自许多客户端的插入被集中在一起,并被编写入一个块。这比执行许多独立的插入要快很多。坏处是,不能返回自动递增的ID,以及系统崩溃时,MySQL还没有来得及插入数据的话,这些数据将会丢失。
强制连接顺序 STRAIGHT_JOIN
SELECT TABLE1.FIELD1, TABLE2.FIELD2 FROM TABLE1 STRAIGHT_JOIN TABLE2 WHERE …
由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按TABLE1、TABLE2的顺序连接表。如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序。
强制使用临时表 SQL_BUFFER_RESULT
SELECT SQL_BUFFER_RESULT * FROM TABLE1 WHERE …
当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁(这样其它的SQL语句就可以对这些记录进行查询了),并且可以长时间地为客户端提供大记录集。
分组使用临时表 SQL_BIG_RESULT和SQL_SMALL_RESULT
SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM TABLE1 GROUP BY FIELD1;
一般用于分组或DISTINCT关键字,这个选项通知MySQL,如果有必要,就将查询结果放到临时表中,甚至在临时表中进行排序。SQL_SMALL_RESULT比起SQL_BIG_RESULT差不多,很少使用。
优化总结:
1.任何情况下SELECT COUNT(*) FROM xxx 是最优选择;
2.尽量减少SELECT COUNT(*) FROM xxx WHERE COL = ‘xxx’ 这种查询;
3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL = ‘xxx’ 的出现。(其中COL非主键)
环境:
MySQL版本:5.0.45
OS:Windows XP SP3
数据表一:sphinx
+———-+——————+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———-+——————+——+—–+———+—————-+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| til | varchar(100) | NO | | | |
| content | text | NO | | | |
| dataline | int(11) | NO | | | |
+———-+——————+——+—–+———+—————-+
记录数:1120100
查询一:
mysql> select count(*) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.00 sec)
查询二:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (2.17 sec)
查询三:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (0.61 sec)
查询四:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (0.61 sec)
查询五:
mysql> select count(id) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.00 sec)
查询六:
mysql> select count(til) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (1 min 38.61 sec)
查询七:
mysql> select count(id) as totalnum from sphinx where id>11000;
+———-+
| totalnum |
+———-+
| 1109100 |
+———-+
1 row in set (0.61 sec)
查询八:
mysql> select count(id) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.03 sec)
结论:
在 select count() 没有 where 条件的时候 select count(*) 和 select count(col) 所消耗的查询时间相差无几。
在 select count() 有 where 条件的时候 select count(col) 所消耗的查询时间 比 select count(*) 明显多出数量级的时间。
1.任何情况下SELECT COUNT(*) FROM xxx 是最优选择;
2.尽量减少SELECT COUNT(*) FROM xxx WHERE COL = ‘xxx’ 这种查询;
3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL = ‘xxx’ 的出现。(其中COL非主键)
环境:
MySQL版本:5.0.45
OS:Windows XP SP3
数据表一:sphinx
+———-+——————+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———-+——————+——+—–+———+—————-+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| til | varchar(100) | NO | | | |
| content | text | NO | | | |
| dataline | int(11) | NO | | | |
+———-+——————+——+—–+———+—————-+
记录数:1120100
查询一:
mysql> select count(*) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.00 sec)
查询二:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (2.17 sec)
查询三:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (0.61 sec)
查询四:
mysql> select count(*) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (0.61 sec)
查询五:
mysql> select count(id) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.00 sec)
查询六:
mysql> select count(til) as totalnum from sphinx where id>1000;
+———-+
| totalnum |
+———-+
| 1119100 |
+———-+
1 row in set (1 min 38.61 sec)
查询七:
mysql> select count(id) as totalnum from sphinx where id>11000;
+———-+
| totalnum |
+———-+
| 1109100 |
+———-+
1 row in set (0.61 sec)
查询八:
mysql> select count(id) as totalnum from sphinx;
+———-+
| totalnum |
+———-+
| 1120100 |
+———-+
1 row in set (0.03 sec)
结论:
在 select count() 没有 where 条件的时候 select count(*) 和 select count(col) 所消耗的查询时间相差无几。
在 select count() 有 where 条件的时候 select count(col) 所消耗的查询时间 比 select count(*) 明显多出数量级的时间。
flash-php的RPC方案amfphp
时间:2009-03-04 17:13:18 来源:http://ilovelate.blog.163.com/blog/static/601420091212142713 作者:
flash里自己有个二进制的数据传输协议Amf, 幸好php里有个amfphp,那就很方便了, 协议会自动转换php和flash的数据类型,本来都是动态语言,啥都好办。
网址:http://www.amfphp.org/ 官方的,目前最新版本1.9 beta2
下载地址: http://sourceforge.net/project/showfiles.php?group_id=72483
另外要安装个可以提升性能的东东:http://www.teslacore.it/wiki/index.php?title=AMFEXT 目前版本0.8.7
将amfphp放到php项目目录下就可以使用了。
注意将Remote Service php 放到 amfphp\services 目录里面就可以使用了,很简单。
贴个session的例子:
flash端:
php端:
<?php
// Wade Arnold: 1/6/2008
// Example is designed to show how to use PHP sessions.
class Counter {
public function __construct() {
// Check if the session is available or create it.
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
}
// Used to increment the session variable count.
public function increment() {
$_SESSION['count']++;
return $_SESSION['count'];
}
// used to destroy the session variable and start over.
public function unregister() {
unset($_SESSION['count']);
return true;
}
// remove the entire session from the server.
public function destroy() {
session_destroy();
return true;
}
}
?>
YY两句,看到热血三国的通讯方式竟然是amfphp的RPC通讯方式的, 这样的话编程模型跟普通的web项目开发就一模一样了, 现在只是说使用了flash界面而已,开发难度大幅度降低。
想想也是, 策略类的游戏,没必要使用客户端游戏的那种socket编程模型,开发起来复杂多了。 可能游戏玩法不一样引起的。如果是有实时战斗的玩法,那必须得socket编程了吧。
时间:2009-03-04 17:13:18 来源:http://ilovelate.blog.163.com/blog/static/601420091212142713 作者:
flash里自己有个二进制的数据传输协议Amf, 幸好php里有个amfphp,那就很方便了, 协议会自动转换php和flash的数据类型,本来都是动态语言,啥都好办。
网址:http://www.amfphp.org/ 官方的,目前最新版本1.9 beta2
下载地址: http://sourceforge.net/project/showfiles.php?group_id=72483
另外要安装个可以提升性能的东东:http://www.teslacore.it/wiki/index.php?title=AMFEXT 目前版本0.8.7
将amfphp放到php项目目录下就可以使用了。
注意将Remote Service php 放到 amfphp\services 目录里面就可以使用了,很简单。
贴个session的例子:
flash端:
// Wade Arnold: 1/6/2008
// Example is designed to show how to use PHP sessions.
package {
// required for flash file and output display
import flash.display.MovieClip;
import fl.events.*;
import flash.events.*;
// required to send/recieve data over AMF
import flash.net.NetConnection;
import flash.net.Responder;
// Flash CS3 Document Class.
public class Counter extends MovieClip {
private var gateway:String = "http://localhost/server/amfphp/gateway.php";
private var connection:NetConnection;
private var responder:Responder;
public function Counter() {
trace("AMFPHP Session Counter Example");
// Event listner for buttons
increment_btn.addEventListener(MouseEvent.CLICK, incrementCounter);
reset_btn.addEventListener(MouseEvent.CLICK, resetCounter);
destroy_btn.addEventListener(MouseEvent.CLICK, destroySession);
// Responder to handle data returned from AMFPHP.
responder = new Responder(onResult, onFault);
connection = new NetConnection;
// Gateway.php url for NetConnection
connection.connect(gateway);
}
// Method run when the "Increment Counter" button is clicked.
public function incrementCounter(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.increment", responder);
}
// Method run when the "Rest Counter" button is clicked.
public function resetCounter(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.unregister", responder);
}
// Method run when the "Destroy Session" button is clicked.
public function destroySession(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.destroy", responder);
}
// Handle a successful AMF call. This method is defined by the responder.
private function onResult(result:Object):void {
response_txt.text = String(result);
}
// Handle an unsuccessfull AMF call. This is method is dedined by the responder.
private function onFault(fault:Object):void {
response_txt.text = String(fault.description);
}
}
}
// Example is designed to show how to use PHP sessions.
package {
// required for flash file and output display
import flash.display.MovieClip;
import fl.events.*;
import flash.events.*;
// required to send/recieve data over AMF
import flash.net.NetConnection;
import flash.net.Responder;
// Flash CS3 Document Class.
public class Counter extends MovieClip {
private var gateway:String = "http://localhost/server/amfphp/gateway.php";
private var connection:NetConnection;
private var responder:Responder;
public function Counter() {
trace("AMFPHP Session Counter Example");
// Event listner for buttons
increment_btn.addEventListener(MouseEvent.CLICK, incrementCounter);
reset_btn.addEventListener(MouseEvent.CLICK, resetCounter);
destroy_btn.addEventListener(MouseEvent.CLICK, destroySession);
// Responder to handle data returned from AMFPHP.
responder = new Responder(onResult, onFault);
connection = new NetConnection;
// Gateway.php url for NetConnection
connection.connect(gateway);
}
// Method run when the "Increment Counter" button is clicked.
public function incrementCounter(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.increment", responder);
}
// Method run when the "Rest Counter" button is clicked.
public function resetCounter(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.unregister", responder);
}
// Method run when the "Destroy Session" button is clicked.
public function destroySession(e:MouseEvent):void {
// Send the data to the remote server.
connection.call("Counter.destroy", responder);
}
// Handle a successful AMF call. This method is defined by the responder.
private function onResult(result:Object):void {
response_txt.text = String(result);
}
// Handle an unsuccessfull AMF call. This is method is dedined by the responder.
private function onFault(fault:Object):void {
response_txt.text = String(fault.description);
}
}
}
php端:
<?php
// Wade Arnold: 1/6/2008
// Example is designed to show how to use PHP sessions.
class Counter {
public function __construct() {
// Check if the session is available or create it.
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
}
// Used to increment the session variable count.
public function increment() {
$_SESSION['count']++;
return $_SESSION['count'];
}
// used to destroy the session variable and start over.
public function unregister() {
unset($_SESSION['count']);
return true;
}
// remove the entire session from the server.
public function destroy() {
session_destroy();
return true;
}
}
?>
YY两句,看到热血三国的通讯方式竟然是amfphp的RPC通讯方式的, 这样的话编程模型跟普通的web项目开发就一模一样了, 现在只是说使用了flash界面而已,开发难度大幅度降低。
想想也是, 策略类的游戏,没必要使用客户端游戏的那种socket编程模型,开发起来复杂多了。 可能游戏玩法不一样引起的。如果是有实时战斗的玩法,那必须得socket编程了吧。
最近在工作中常常用ssh登录某个节点的服务器解析域名的时间非常长:
#time ssh
real 0m19.928s
user 0m0.008s
sys 0m0.001s
可以看到登录这个点服务器需要近20秒的时间;
然后用nslookup检查了这个域名ip地址:
报了;; connection timed out; no servers could be reached的错误;
用ping是可以解析,不过解析时间也很长;
这个问题的原因,目前还不是很清楚,怀疑是否是新启用的ip地址可能存在这方面的情况;
ssh登录缓慢的问题可以通过修改sshd_config文件中的GSSAPI options
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
全部注释掉,然后重启sshd服务;
再测试登录
#time ssh
real 0m2.229s
user 0m0.006s
sys 0m0.002s
恢复正常!
#time ssh
real 0m19.928s
user 0m0.008s
sys 0m0.001s
可以看到登录这个点服务器需要近20秒的时间;
然后用nslookup检查了这个域名ip地址:
报了;; connection timed out; no servers could be reached的错误;
用ping是可以解析,不过解析时间也很长;
这个问题的原因,目前还不是很清楚,怀疑是否是新启用的ip地址可能存在这方面的情况;
ssh登录缓慢的问题可以通过修改sshd_config文件中的GSSAPI options
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
全部注释掉,然后重启sshd服务;
再测试登录
#time ssh
real 0m2.229s
user 0m0.006s
sys 0m0.002s
恢复正常!
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
StartServers 10
MinSpareServers 10
MaxSpareServers 15
ServerLimit 2000
MaxClients 2000
MaxRequestsPerChild 10000
查看httpd进程数(即prefork模式下Apache能够处理的并发请求数):
Linux命令:
ps -ef | grep httpd | wc -l
返回结果示例:
1388
表示Apache能够处理1388个并发请求,这个值Apache可根据负载情况自动调整,我这组服务器中每台的峰值曾达到过2002。
查看Apache的并发请求数及其TCP连接状态:
Linux命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
(这条语句是从新浪互动社区事业部技术总监王老大那儿获得的,非常不错)
返回结果示例:
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
其中的SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。
关于TCP状态的变迁,可以从下图形象地看出:
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
StartServers 10
MinSpareServers 10
MaxSpareServers 15
ServerLimit 2000
MaxClients 2000
MaxRequestsPerChild 10000
查看httpd进程数(即prefork模式下Apache能够处理的并发请求数):
Linux命令:
ps -ef | grep httpd | wc -l
返回结果示例:
1388
表示Apache能够处理1388个并发请求,这个值Apache可根据负载情况自动调整,我这组服务器中每台的峰值曾达到过2002。
查看Apache的并发请求数及其TCP连接状态:
Linux命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
(这条语句是从新浪互动社区事业部技术总监王老大那儿获得的,非常不错)
返回结果示例:
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
其中的SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。
关于TCP状态的变迁,可以从下图形象地看出:
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
中文空格这里面有好几种:没有简单的解决问题的方式,比如半角全角空格,比如段落符都会显示为空白的,然后让人们误解它是空格,所以去掉空格之前一定要先确认自己的是不是空格,我下面分析一下这两种的解决办法。
(1)/[\s| ]+/这个就可以,注意|后面的跟的是全角空格
(2)mb中的正则替换也可以试试
另外注意使用Unicode的时候,加上正则表达式描述符u
但由于汉语中显示为空格模样的有很多个,比如说我下面碰到的这么一个,它的unicode编码为C2A0,使用下面的表达式就能解决问题。
这里有个细节: \xc2a0本来是一个Unicode字符,但是不能匹配多个,只能替换一个,【这里可能是因为字节的原因】后来突然找到这么一种写法,解决了问题,另外为了避免,中文空格和英文空格相混杂的情形,后面又加了个\s来清除。
其实在Unicode上的正则表达式确实不怎么好用。
阅读全文
(1)/[\s| ]+/这个就可以,注意|后面的跟的是全角空格
(2)mb中的正则替换也可以试试
另外注意使用Unicode的时候,加上正则表达式描述符u
但由于汉语中显示为空格模样的有很多个,比如说我下面碰到的这么一个,它的unicode编码为C2A0,使用下面的表达式就能解决问题。
$new['content'] = preg_replace('/^[(\xc2\xa0)|\s]+/', '', $new['content']);
这里有个细节: \xc2a0本来是一个Unicode字符,但是不能匹配多个,只能替换一个,【这里可能是因为字节的原因】后来突然找到这么一种写法,解决了问题,另外为了避免,中文空格和英文空格相混杂的情形,后面又加了个\s来清除。
其实在Unicode上的正则表达式确实不怎么好用。
阅读全文
mysql> select distinct(UserNumber),Score_TT from Tbl_Score where FYear = "2009" and FWeek = '53' order by Score_TT desc limit 0,10;
+-----------+--------+
| UserNumber | Score_TT |
+-----------+--------+
| 70213303* | 1800 |
| 78400557* | 1450 |
| 45598211* | 1410 |
| 7575629* | 1200 |
| 30394912* | 1148 |
| 98649685* | 1050 |
| 6653828* | 850 |
| 38200298* | 800 |
| 80496539* | 800 |
| 18064165* | 670 |
+-----------+--------+
10 rows in set (0.37 sec)
mysql> select count(distinct UserNumber),UserNumber,Score_TT from Tbl_Score where FYear = "2009" and FWeek = '53' group by UserNumber order by Score_TT desc limit 0,10;
+---------------------+-----------+--------+
| count(distinct UserNumber) | UserNumber | Score_TT |
+---------------------+-----------+--------+
| 1 | 70213303* | 1800 |
| 1 | 78400557* | 1450 |
| 1 | 45598211* | 1410 |
| 1 | 7575629* | 1200 |
| 1 | 30394912* | 1148 |
| 1 | 98649685* | 1050 |
| 1 | 6653828* | 850 |
| 1 | 80496539* | 800 |
| 1 | 38200298* | 800 |
| 1 | 18064165* | 670 |
+---------------------+-----------+--------+
来源:
在使用 mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的。所以我花了很多时间来研究这个问题,网上也查不到解决方案,期间把朋友拉来帮忙,结果是我们两人都郁闷了!
下面先来看看例子:
table
id name
1 a
2 b
3 c
4 c
5 b
库结构大概这样,这只是一个简单的例子,实际情况会复杂得多。
比如我想用一条语句查询得到name不重复的所有数据,那就必须使用distinct去掉多余的重复记录。
select distinct name from table
得到的结果是:
name
a
b
c
好像达到效果了,可是,我想要得到的是id值呢?改一下查询语句吧:
select distinct name, id from table
结果会是:
id name
1 a
2 b
3 c
4 c
5 b
distinct怎么没起作用?作用是起了的,不过他同时作用了两个字段,也就是必须得id与name都相同的才会被排除……
我们再改改查询语句:
select id, distinct name from table
很遗憾,除了错误信息你什么也得不到,distinct必须放在开头。难到不能把distinct放到where条件里?能,照样报错。。。。。。。
很麻烦吧?确实,费尽心思都没能解决这个问题。没办法,继续找人问。
拉住公司里一JAVA程序员,他给我演示了oracle里使用distinct之后,也没找到mysql里的解决方案,最后下班之前他建议我试试group by。
试了半天,也不行,最后在mysql手册里找到一个用法,用group_concat(distinct name)配合group by name实现了我所需要的功能,兴奋,天佑我也,赶快试试。
报错。。。。。。。。。。。。郁闷。。。。。。。连mysql手册也跟我过不去,先给了我希望,然后又把我推向失望,好狠哪。。。。
再仔细一查,group_concat函数是4.1支持,晕,我4.0的。没办法,升级,升完级一试,成功。。。。。。
终于搞定了,不过这样一来,又必须要求客户也升级了。
突然灵机一闪,既然可以使用group_concat函数,那其它函数能行吗?
赶紧用count函数一试,成功,我。。。。。。。想哭啊,费了这么多工夫。。。。。。。。原来就这么简单……
现在将完整语句放出:
select *, count(distinct name) from table group by name
结果:
id name count(distinct name)
1 a 1
2 b 1
3 c 1
最后一项是多余的,不用管就行了,目的达到。
唉,原来mysql这么笨,轻轻一下就把他骗过去了,郁闷也就我吧(对了,还有容容那家伙),现在拿出来希望大家不要被这问题折腾。
哦,对,再顺便说一句,group by 必须放在 order by 和 limit之前,不然会报错.
更郁闷的事情发生了,在准备提交时容容发现,有更简单的解决方法:
select id, name from table group by name
看来对mysql的了解还是太肤浅了,不怕被笑话,发出来让大家别犯同样的错误。
# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
如果要恢复,只要:
# echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
即可,
挺方便,不要去专门使用ipchains或者iptables了。
或者以root进入Linux系统,然后编辑文件icmp_echo_ignore_all
# vi /proc/sys/net/ipv4/icmp_echo_ignore_all
将其值改为1后为禁止PING
将其值改为0后为解除禁止PING
[root@redhat7 root]# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
如果要恢复,只要:
[root@redhat7 root]# echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
即可,挺方便,不要去专门使用ipchains或者iptables了。
在/etc/rc.d/rc.local文件里添加一行命令:echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
这样每次启动系统后都将自动运行,可以阻止你的系统响应任何从外部/内部来的ping请求,
就没有人能ping通你的机器并收到响应,可以大大增强站点和系统的安全性。
如果要恢复,只要:
# echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
即可,
挺方便,不要去专门使用ipchains或者iptables了。
或者以root进入Linux系统,然后编辑文件icmp_echo_ignore_all
# vi /proc/sys/net/ipv4/icmp_echo_ignore_all
将其值改为1后为禁止PING
将其值改为0后为解除禁止PING
[root@redhat7 root]# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
如果要恢复,只要:
[root@redhat7 root]# echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
即可,挺方便,不要去专门使用ipchains或者iptables了。
在/etc/rc.d/rc.local文件里添加一行命令:echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
这样每次启动系统后都将自动运行,可以阻止你的系统响应任何从外部/内部来的ping请求,
就没有人能ping通你的机器并收到响应,可以大大增强站点和系统的安全性。
SELECT mail
FROM `t_import_mail`
WHERE 1
GROUP BY mail
HAVING count( 0 ) >1
LIMIT 0 , 30
select FQQ,FUserID,count(*) as ct from `Tbl_User_**` GROUP BY FQQ HAVING ct > 1;
//查出表某个字段产生重复值的所有记录
可以用group by 来查出不重复的记录,但是我想查出重复的记录该如何写sql语句呢?
先看这个,
select uid,email,count(*) as ct from `edm_user081217` GROUP BY email
然后看这个,就容易理解了
select uid,email,count(*) as ct from `edm_user081217` GROUP BY email HAVING ct > 1
以下是having和where的区别:
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
作用的对象不同。WHERE 子句作用于表和视图,HAVING 子句作用于组。
WHERE 在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算), 而 HAVING 在分组和聚集之后选取分组的行。因此,WHERE 子句不能包含聚集函数; 因为试图用聚集函数判断那些行输入给聚集运算是没有意义的。相反,HAVING 子句总是包含聚集函数。(严格说来,你可以写不使用聚集的 HAVING 子句,但这样做只是白费劲。同样的条件可以更有效地用于 WHERE 阶段。)
在前面的例子里,我们可以在 WHERE 里应用城市名称限制,因为它不需要聚集。 这样比在 HAVING 里增加限制更加高效,因为我们避免了为那些未通过 WHERE 检查的行进行分组和聚集计算
综上所述:
having一般跟在group by之后,执行记录组选择的一部分来工作的。
where则是执行所有数据来工作的。
再者having可以用聚合函数,如having sum(qty)>1000
PRIMARY, INDEX, UNIQUE 这3种是一类
PRIMARY 主键。 就是 唯一 且 不能为空。
INDEX 索引,普通的
UNIQUE 唯一索引。 不允许有重复。
FULLTEXT 是全文索引,用于在一篇文章中,检索文本信息的。
举个例子来说,比如你在为某商场做一个会员卡的系统。
这个系统有一个会员表
有下列字段:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT
那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息 , 如果需要建索引的话,可以选择 FULLTEXT,全文搜索。
不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
阅读全文
PRIMARY 主键。 就是 唯一 且 不能为空。
INDEX 索引,普通的
UNIQUE 唯一索引。 不允许有重复。
FULLTEXT 是全文索引,用于在一篇文章中,检索文本信息的。
举个例子来说,比如你在为某商场做一个会员卡的系统。
这个系统有一个会员表
有下列字段:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT
那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息 , 如果需要建索引的话,可以选择 FULLTEXT,全文搜索。
不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
阅读全文
Definition and Usage
定义和用法
The round() function rounds a number to the nearest integer.
round()函数的作用是:对浮点数进行四舍五入取整。
Syntax
语法
round(x,prec)
Parameter
参数 Description
描述
x Required. The number to be round
必要参数。指定需要进行操作的数值对象
prec Optional. The number of digits after the decimal point
可选参数。指定小数位数
实例,指定小数位数为2位:
第二位小于5,情况:
定义和用法
The round() function rounds a number to the nearest integer.
round()函数的作用是:对浮点数进行四舍五入取整。
Syntax
语法
round(x,prec)
Parameter
参数 Description
描述
x Required. The number to be round
必要参数。指定需要进行操作的数值对象
prec Optional. The number of digits after the decimal point
可选参数。指定小数位数
实例,指定小数位数为2位:
<?php
echo(round(0.6025,3));
?>
[~]# php test.php
0.603
echo(round(0.6025,3));
?>
[~]# php test.php
0.603
第二位小于5,情况:
<?php
echo(round(0.6024,3));
?>
[~]# php test.php
0.602
echo(round(0.6024,3));
?>
[~]# php test.php
0.602