2014年4月30日星期三

CentOS6部署phpmyadmin;部署Discuz;部署phpwind

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
CentOS6部署phpmyadmin;部署Discuz;部署phpwind  阅读原文»

用户名:zys467754239 文章数:34 评论数:0
访问量:1710:683:374:3 注册日期:2012-04-18

CentOS6部署phpmyadmin;部署Discuz;部署phpwind;部署phpBB

第一部分:

一、yum安装LAMP平台
二、部署phpMyAdmin

第二部分:
一、
搭建论坛系统Discuz

二、搭建论坛系统PhpWind

三、搭建论坛系统PhpBB

第三部分

一、部署wordpress个人博客系统

===============================================================================

一、phpMyAdmin简介

1.phpMyAdmin是以PHP为基础而开发的一个以WEB方式来管理Mysql数据库的工具,phpMyAdmin提供了一个比较人性化的网页界面,操作起来非常简单易用。对于一些对SQL语句不太熟悉的人来使用,是最好不过的一个工具了。
phpMyAdmin官方网站下载地址:http://www.phpmyadmin.net/home_page/downloads.php

2.安装LAMP平台

# yum -y install http php php-mysql php-mbstring mysql mysql-server

3.修改Apache主配置文件,添加默认主页如下:

# vim /etc/httpd/conf/httpd.conf
DirectoryIndex index.php index.html index.html.var

4.启动http与mysql服务

# service httpd start
# service mysqld start

5.在默认网页存放新建一个index.php文件,写一个测试语句,是否能够连接数据库,数据库用户"root",默认没有密码,我们设置一个密码;如下;

# mysqladmin -uroot -p password "phpmyadmin"
# vim /var/www/html/index.php
<h1>www.phpmyadmin.com</h1>
$Con=mysql_connect('127.0.0.1','phpmyadmin','phpmyadmin');
echo "SUCCESS...";
echo "FAILURE...";

6.浏览器测试访问

wKiom1Nf03uhDtBhAACyw9Iq5pM733.jpg

7.修改/etc/httpd/conf/httpd.conf文件,为phpmyadmin创建一个虚拟主机;如:

# cd /etc/httpd/conf
# cp httpd.conf httpd.conf.bak
# vim httpd.conf
NameVirtualHost 192.168.0.104:80
<VirtualHost 192.168.0.104:80>
ServerAdmin zhengyansheng@cdvcloud.com
DocumentRoot /var/www/html/phpmyadmin
ServerName www.phpmyadmin.com
ErrorLog logs/allentuns-error_log
CustomLog logs/allentuns-access_log common

8.重新载入配置文件

# service httpd reload

9.解压phpMyAdmin软件包

# cd /usr/local/src
# tar xf phpMyAdmin-4.1.14-all-languages.tar.bz2 -C /var/www/html/
# mv phpMyAdmin-4.1.14-all-languages phpmyadmin

10.由于没有DNS服务器解析,需要在本地Hosts文件中添加如下记录:

C:\Windows\System32\Drivers\etc\hosts #打开此文件添加如下内容
192.168.0.104 www.phpmyadmin.com

11、客户端打开浏览器验证是否能成功登?div style="border-bottom:1px solid #aaa;margin-bottom:25px">【开源计划】 kzfont――bmfont 的 texturepacker 导出插件  阅读原文»

【开源计划】 kzfont――bmfont 的 texturepacker 导出插件

bmfont

一个借助图片来实现自定义字体的方案。优点是简单实用,但是需要一个好用的工具支持。

现有的工具:

  • Bitmap Font Generator

这算是官方版本了,地址是 http://www.angelcode.com/products/bmfont/

教程 http://blog.csdn.net/keshuiyun/article/details/9960589

  上面的工具能解决有没有的问题,能用但是非常不方便。本质上都是字体转图片而已,但是实际上我们的需要可能是效果丰富的美术字,要想用上面的工具完成和 photoshop 上生成的字体效果基本上是不可能的。

美术想要的效果是这样的:

wKiom1NfxxzRjCFFAABygqKi3dk250.jpg 或者这样的wKioL1NfxvKh2YKNAABmzHPpio4958.jpg

但是使用工具只能做到:

wKioL1Nf03yDzMC9AADVvYPIhSA271.jpg

或许,你能做的更好,但是,相信我,大部分的同学是做不到的。

kzfont

于是,就有了 kzfont。这个其实是 TexturePacker 的一个 bmfont 导出工具。

你只需要2步就能方便的做出一个 fnt 文件了。

1,准备一堆单独切割好的字体图片,类似于

wKiom1Nf1MOBIPxYAAAgX-yzClw283.jpgwKioL1Nf1JnRa75iAAAmEjUepNo246.jpg 这样的,一个字一张图

记得图片名就是这个中文字(如果需要的字符不能用作文件名,可以使用 u+uncode 值 来替换支付)

2.把图片拖到 TexturePacker 里面,选择 kzfont 导出即可。附件是一个生成的示例.

TexturePacker 自定义导出插件

1,解压 kzfont到你满意的目录

2.打开 TexturePacker,在设置里面填入 kzfont 的上一级目录

texturepacker-preferences.png

3.确定.

4.在导出格式(Data format)里面就能看到 kzfont 了

如何获得

如果你觉得这个工具不错,希望你对我提供资金上的支持,以便我在今后制作出更多更好的工具, 谢谢。

捐赠地址https://me.alipay.com/kingzeus (支付宝)

无论金额多少,我都会发送一份 kzfont 到你的邮箱,并且希望你能把使用的反馈告诉我。

关于捐赠

制作这个工具其实属于偶然,算是折腾 texture packer 的一个副产品吧。但是一路用下来,的确方便好多。好吧,我不靠这个挣钱,只是想尝试一下募集一些捐赠。这些捐赠不是用来补偿我的劳动,而是帮助我购买相关的软件(texture packer)并且让我知道这个工具真的可以帮助到你。

正版软件

  • texture packer,升级终身授权版本($59.95 + tax)

作为一个程序员,其实我还是可以承受这个价格的。但是,作为程序员,我更希望能够通过帮助到很多人来得到一些奖励或者说是鼓励。好吧,这个工具估计对我的生活不会有太大帮助,但是如果能用这个来买套软件,的确是件很酷的事情,绝对值得我在 老G 的群里炫耀一番了。

当然 没有任何的捐赠我也会坚持下去的,希望这个小小的捐赠请求没有引起你的反感。

谢谢 :)

最后是说好的开源计划

捐赠只是一个小小的实验,等我凑到了一个 TP 就开源了,或者如果一段时间之后,还是不能买 TP 的话,我也会开源的啦,好了,如果,你不愿意捐赠,那就请稍等一阵子吧,至少,让我也试下效果啊。

补充

一发贴,立马有了二位同学出现了,好开心啊,这个真心可以炫耀下的.

本文出自 "游戏 人生" 博客,转载请与作者联系!

返回顶部
请输入验证码:

阅读更多内容

2014年4月29日星期二

Android--ViewPager多页面滑动切换以及动画效果 - 我爱物联网

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Android--ViewPager多页面滑动切换以及动画效果 - 我爱物联网  阅读原文»

背景

ViewPager。它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换。这个附加包是android-support-v4.jar。

根据屏幕的分辨率和图片的宽度计算动画移动的偏移量

image

代码

viewpager.xml

界面设计很简单,第一行三个头标,第二行动画图片,第三行页卡内容展示。界面设计很简单,第一行三个头标,第二行动画图片,第三行页卡内容展示。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="vertical" >

<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width
="fill_parent"
android:layout_height
="100.0dip"
android:background
="#FFFFFF" >

<TextView
android:id="@+id/text1"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:layout_weight
="1.0"
android:gravity
="center"
android:text
="页卡1"
android:textColor
="#000000"
android:textSize
="22.0dip" />

<TextView
android:id="@+id/text2"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:layout_weight
="1.0"
android:gravity
="center"
android:text
="页卡2"
android:textColor
="#000000"
android:textSize
="22.0dip" />

<TextView
android:id="@+id/text3"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:layout_weight
="1.0"
android:gravity
="center"
android:text
="页卡3"
android:textColor
="#000000"
android:textSize
="22.0dip" />
</LinearLayout>

<ImageView
android:id="@+id/cursor"
android:layout_width
="fill_parent"
android:layout_height
="wrap_content"
android:scaleType
="matrix"
android:src
="@drawable/a" />

<android.support.v4.view.ViewPager
android:id="@+id/vPager"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:layout_gravity
="center"
android:layout_weight
="1.0"
android:background
="#000000"
android:flipInterval
="30"
android:persistentDrawingCache
="animation" />


</LinearLayout>

我们要展示三个页卡,所以还需要三个页卡内容的界面设计,这里我们只设置了背景颜色,能起到区别作用即可。3个lay.xml,设置颜色不同。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:orientation
="vertical"
android:background
="#1586FF" >
</LinearLayout>

初始化头标

/**
* 初始化头标
*/
private void InitTextView() {
t1
= (TextView) fi
【ORACLE】物理体系结构 - Jan.Xiao  阅读原文»

一、ORACLE 物理体系结构

  1. 原理结构图

各部分解释:

PGA: 私有内存区,仅供当前发起用户使用。

三个作用

  1. 用户登录后的session信息会保存在PGA。
  2. 执行排序,如果内存不够,oracle会在临时表空间中完成
  3. 保存用户权限信息

SGA: 包含共享池,数据缓冲区,日志缓冲区以及一些相关的进程。

DATABASE: 数据最终存放的地方,其中一块区域是日志存放区。数据和记录日志又由DBWR和LGWR来写入数据库和重做日志组,待一个重做日志组满了之后切换到下一个,等到循环了一次之后,原来排序为第一组的日志会被ARCH进程写入归档日志。

2结构深入

2.1 从一条查询sql语句解析结构

假设有一条sql: select * from user where user_id='20'

  1. Sql被解析后,(1区)PGA保存其登陆和权限信息。这一点必须注意,如果保存了该信息,下次调用sql的时候就不需要重新校验,直接玩PGA里取就行了。
  2. 随后该sql会匹配一条唯一的HASH值并到达2区的共享池,共享池判断此HASH值是否之前已经存在,如果存在就直接执行就OK了;如果不存在,就要检查sql的语法、语义等进行验证并解析。解析什么呢?就是要把select * from user where user_id='20' 这条语句,在user_id存在索引的情况下,oracle对最优COST做出选择(到底是索引扫描还是全表扫描),作出选择后oracle会把改执行计划和之前的那条HASH值放在一起。
  3. 带着条件,sql下一步会到数据缓冲区中查找是否存在user_id为20的记录。如果缓冲区有则马上返回结果;如果无,则要到3区(database)中查找,无论是否找到都要返回结果。

2.2 从一条更新sql语句解析结构

假设有一条sql:update user set user_name='萧红'

  1. 如上步骤1.2 。
  2. 把数据的操作记录写到重做日志
  3. 写入数据库中,持久化数据,把数据库user表的user_name 字段都改为萧红。

3提交与回滚

  1. 当用户提交commit的时候,数据并不会马上刷进数据库。数据何时会被刷入数据库?

    这与CKPT进程有关,当缓冲区的数据量达到一定的程度时,CKPT进程会被触发,数据此时才批量刷入数据库。当刷入数据库前断电了怎么办?REDU机制重新执行日志恢复数据。

      2. ROLLBACK 执行的是UNDO


本文链接:【ORACLE】物理体系结构,转载请注明。

阅读更多内容

2014年4月28日星期一

zabbix企业应用之服务器硬件信息监控

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
zabbix企业应用之服务器硬件信息监控  阅读原文»

zabbix企业应用之服务器硬件信息监控

之前介绍的zabbix监控都是属于监控服务方面,现在介绍一下zabbix监控服务器硬件信息的。

由于我公司服务器都是使用dell(我公司是手游方面,服务器全部是dell),服务器型号有r410、r420、r710、r720,系统有centos 5.x、centos 6.x 、redhat 5.x、redhat 6.x、ubuntu 12.04、ubuntu 12.04.4等版本,对于硬件监控,我测试过ipmi、megacli、smart等,但这些监控软件的监控内容都比较少,没有通用的那种,最后找到了dell专门的omsa,满足了我的需求,下面就介绍一下使用omsa来监控dell服务器的硬件信息。

目前我监控以下的硬件信息:

1、cpu处理器状态

2、cpu省电模式状态(如果开启了省电模式,在压力大的时候,会很卡的)

3、raid状态(比如做了哪个raid模式,raid状态是否正常)

4、内存状态(可以查看当前服务器最大支持多少内存,当前多少内存,如果内存有问题,可以显示哪个位置内存故障)

5、机器温度状态(监控机器的温度是否超过阀值)

6、物理硬盘状态(监控物理硬盘是否有故障)

7、电源状态(是单电还是双电,是否有故障)

8、系统面板CMOS电池(cmos电池是否有故障)

9、网卡状态(当前的网卡数量,以及网卡是否有问题)

10、风扇(当前的风扇数量,以及是否有故障)

默认是cpu省电模式监控关闭报警,其他的监控都是15分钟监控一次,如果连续2次都有问题则报警通知。

下面是监控图

1、硬件正常的服务器监控截图

wKioL1NdxYuAFlirAAQxcbtC95U846.jpg

2、部分硬件不正常的监控图

wKiom1NdxmOSUNQSAARq-q-aIyU215.jpg可以看到此服务器的cpu开启了省电模式,并且内存条有问题

经过命令行查看,发现有问题的内存条是第一个插槽

wKioL1NdxmbyfKYWAADg1vjYLso218.jpg

下面是安装方法:

一、客户端

A.在redhat或者centos系统里安装

1、安装dell的yum源

  wget -q -O - http://linux.dell.com/repo/hardware/latest/bootstrap.cgi | bash  

2、安装omsa

  yum install srvadmin-all  

3、做软连接

  ln -s /opt/dell/srvadmin/sbin/omreport /usr/bin/omreport  ln -s /opt/dell/srvadmin/sbin/omconfig /usr/bin/omconfig  

4、关闭web模式(仅允许运行cli)

  echo "/usr/bin/omconfig system webserver action=stop" >>/opt/dell/srvadmin/sbin/srvadmin-services.sh  

5、启动omsa

  /opt/dell/srvadmin/sbin/srvadmin-services.sh start  

6、把omsa加入到开机启动里

  echo "/opt/dell/srvadmin/sbin/srvadmin-services.sh start">>/etc/rc.local  

以上是在centos或者redhat系统里安装omsa。

B.下面是在ubuntu下的安装

1、增加源

  echo 'deb http://linux.dell.com/repo/community/ubuntu precise openmanage' | sudo tee -a /etc/apt/sources.list.d/linux.dell.com.sources.list  

2、检测与增加key

  gpg --keyserver pool.sks-keyservers.net --recv-key 1285491434D8786F  gpg -a --export 1285491434D8786F | sudo apt-key add -  

3、更新源

  apt-get update -y  

4、安装omsa

  apt-get install srvadmin-all -y  

5、做软连接

  ln -s /opt/dell/srvadmin/sbin/omreport /usr/bin/omreport  ln -s /opt/dell/srvadmin/sbin/omconfig /usr/bin/omconfig  

6、启动cli模式omsa

  service dataeng start  

C.zabbix客户端的配置

1、下面是在zabbix_agentd.conf里配置

  #follow is monitor hardware  UserParameter=hardware_battery,omreport chassis batteries|awk'/^Status/{if($NF=="Ok") {print 1} else {print 0}}'  UserParameter=hardware_cpu_model,awk-vhardware_cpu_crontol=`sudoomreport chassis biossetup|awk'/C State/{if($NF=="Enabled") {print 0} else {print 1}}'` -vhardware_cpu_c1=`sudoomreport chassis biossetup|awk'/C1[-|E]/{if($NF=="Enabled") {print 0} else {print 1}}'` 'BEGIN{if(hardware_cpu_crontol==0 && hardware_cpu_c1==0) {print 0} else {print 1}}'  UserParameter=hardware_fan_health,awk-vhardware_fan_number=`omreport chassis fans|grep-c "^Index"` -vhardware_fan=`omreport chassis fans|awk'/^Status/{if($NF=="Ok") count+=1}END{print count}'` 'BEGIN{if(hardware_fan_number==hardware_fan) {print 1} else {print 0}}'  UserParameter=hardware_memory_health,awk-vhardware_memory=`omreport chassis memory|awk'/^Health/{print $NF}'` 'BEGIN{if(hardware_memory=="Ok") {print 1} else {print 0}}'  UserParameter=hardware_nic_health,awk-vhardware_nic_number=`omreport chassis nics |grep-c "Interface Name"` -vhardware_nic=`omreport chassis nics |awk'/^Connection Status/{print $NF}'|wc-l` 'BEGIN{if(hardware_nic_number==hardware_nic) {print 1} else {print 0}}'  UserParameter=hardware_cpu,omreport chassis processors|awk'/^Health/{if($NF=="Ok") {print 1} else {print 0}}'  UserParameter=hardware_power_health,awk-vhardware_power_number=`omreport chassis pwrsupplies|grep-c "Index"` -vhardware_power=`omreport chassis pwrsupplies|awk'/^Status/{if($NF=="Ok") count+=1}END{print count}'` 'BEGIN{if(hardware_power_number==hardware_power) {print 1} else {print 0}}'  UserParameter=hardware_temp,omreport chassis temps|awk'/^Status/{if($NF=="Ok") {print 1} else {print 0}}'head-n 1  UserParameter=hardware_physics_health,awk-vhardware_physics_disk_number=`omreport storage pdisk controller=0grep-c "^ID"` -vhardware_physics_disk=`omreport storage pdisk controller=0awk'/^Status/{if($NF=="Ok") count+=1}END{print count}'` 'BEGIN{if(hardware_physics_disk_number==hardware_physics_disk) {print 1} else {print 0}}'  UserParameter=hardware_virtual_health,awk-vhardware_virtual_disk_number=`omreport storage vdisk controller=0grep-c "^ID"` -vhardware_virtual_disk=`omreport storage vdisk controller=0awk'/^Status/{if($NF=="Ok") count+=1}END{print count}'` 'BEGIN{if(hardware_virtual_disk_number==hardware_virtual_disk) {print 1} else {print 0}}'  

2、重启zabbix_agentd服务

  ps-efgrepzabbixgrep-vgrepawk'{print $2}'xargskill-9  /usr/local/zabbix/sbin/zabbix_agentd-c /usr/local/zabbix/conf/zabbix_agentd.conf  

如果需要在其他系统里安装,请参看官方wiki,地址是http://linux.dell.com/wiki/index.php/Repository/hardware

二、服务端

1、模板导入

把Template Hardware Monitor导入到zabbix里(模板在附件),具体操作不介绍。

2、主机关联模板

把需要监控的硬件服务器关联此模板即可

本文出自 "吟�技术交流" 博客,请务必保留此出处http://dl528888.blog.51cto.com/2382721/1403893

Domino9下邮件组群组分类  阅读原文»

Domino9下邮件组群组分类
分享至 一键收藏,随时查看,分享好友!

阅读更多内容

C++ Jsoncpp源代码编译与解析Json - 旭东的博客

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
C++ Jsoncpp源代码编译与解析Json - 旭东的博客  阅读原文»

1.Json 数据表示方式介绍

  这个可以看之前的一个文章里面有说明:Java解析(读取)Json数据

2.C++ Jsoncpp

2.1 Jsoncpp介绍

  (1)JsonCpp主要包含三种类型的class:Value Reader Writer;

    Json::Value 是jsoncpp 中最基本、最重要的类,用于表示各种类型的对象,jsoncpp 支持的对象类型可见 Json::ValueType 枚举值。

    Json::Reader 是用于读取的,说的确切点,是用于将字符串转换为 Json::Value 对象的。

    Json::Writer 类是一个纯虚类,并不能直接使用。在此我们使用 Json::Writer 的子类:Json::FastWriter、Json::StyledWriter、Json::StyledStreamWriter。

  (2)Jsoncpp中所有对象、类名都在namespace json中,包含json.h即可

2.2 Jsoncpp的下载与编译

  下载下来的jsoncpp必须要编译才能使用,在ubuntut上使用如下:

apt-get install scons
####下载jsoncpp
-src-0.5.0.tar.gz######
tar
-xvzf jsoncpp-src-0.5.0.tar.gz
cd jsoncpp
-src-0.5.0
scons platform
=linux-gcc

  gcc版本是4.6的,上面的命令执行完后,会在jsoncpp-src-0.5.0/libs/linux-gcc-4.6目录下面生成库文件:

  (1)libjson_linux-gcc-4.6_libmt.a

  (2)libjson_linux-gcc-4.6_libmt.so

  之后,将动态链接库libjson_linux-gcc-4.6_libmt.so,添加到搜索路径中,参照:linux找不到动态链接库 .so文件的解决方法

3.Jsoncpp使用代码示例

3.1 程序解析json数据

解析下面的文件JsonText,文件如下:

{
"name": "json",
"array": [
"123",
"456",
"789"
]
}

代码(c.cpp):

1 #include "json/json.h"
2 #include <string>
3 #include <stdlib.h>
4 #include <iostream>
5 #include <fstream>
6 using namespace std;
7 int main()
8 {
9 ifstream is;
10 is.open ("JsonText", std::ios::binary );
11 Json::Reader reader;
12 Json::Value root;
13 if(reader.parse(is,root)) ///root保存整个Json对象的value
14 {
15 if(!root["name"].isNull())
16 {
17 cout<<root["name"].asString()<<endl; ///读取元素
18 Json::Value arrayObj = root["array"];
19 for(int i=0 ; i< arrayObj.size() ;i++)
20 {
21 cout<<arrayObj.asString()<<endl;
22 }
23 }
24 }
25 return 0;
26 }

编译、链接、执行:

  g++ c.cpp -I ./include/ -L./libs/linux-gcc-4.6/ -ljson_linux-gcc-4.6_libmt -o C

  ./C

执行结果:

  json

  123

  456

  789

3.2 程序生成json数据

代码:

1 #include <iostream>
2 #include <string>
3 #include "json/json.h"
4
5 int main(void)
6 {
7 Json::Value root;
8 Json::Value arrayObj;
9 Json::Value item;
10
11 for (int i = 0; i < 2; i ++)
12 {
13 item["key"] = i;
14 //arrayObj.append(item); ///给arrayObj中添加元素(arrayObj变为数组)
15 arrayObj.append(i); ///给arrayObj中添加元素(arrayObj变为数组)
16 }
数据挖掘算法之k-means算法 - 潇一  阅读原文»

k-means算法可以说是数据挖掘中十大经典算法之一了,属于无监督的学习。该算法由此衍生出了很多类k-means算法,比如k中心点等等,在数据挖掘领域,很多地方都会用到该算法,他能够把相似的一类很好的聚在一起。一类指的是,他们之间的相似度较高,计算相似度的常用度量有欧氏距离、余弦定理等。本算法采用的是欧式距离度量。这个对理解k-means算法不会造成任何实质性的影响。

为了更好的说明k-means算法是把属于一类的对象聚成一个簇的,下面贴两张图,一张是100个数据对象是,K=2的情况【图1】。

另外一张是1000个数据对象,k=3的情况,希望大家看完图能够加深对K-means算法的理解。

[图1 objectNum=100 k=2]

[图2 objectNum=1000 k=3]

k-means算法的中心思想其实就是迭代,通过不断的迭代,使聚类效果达到局部最优,为什么我们说局部最优呢?因为K-means算法的效果的优劣性和最初选取的中心点是有莫大关系的,我们只能在初始中心点的基础上达到局部最优解。

k-means算法的过程如下:

1)从N个文档随机选取K个文档作为质心(即中心点)
2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类
3)重新计算已经得到的各个类的质心
4)迭代2~3步直至新的质心与原质心相等或小于指定阈值(我们这里实际上用迭代次数代替了阈值的功能),算法结束
输入: 一个数据集dataset,类个数k
输出:k个小的数据集,也就是K个类。
该算法会有一些缺点主要是:
1、计算量大,不断的迭代,不断的计算,计算量大事在所难免了。
2、K值的指定也是一个难点,很多时候我们并不知道k是多少?
3、只能得到局部最优解,这一点我们在前面已经讨论过了。
算法能够一行行读txt数据,当然其他格式数据也是可以的,稍微改动下即可。相当方便实用。本着开源的方式,附上90%代码:void produceData(string fileName,int maxNum,int objectNum);方法代码没有附上,该方法用来产生随机数据。如果需要全部源代码请点赞后留下email地址,我将会在第一时间发到你邮箱,不便之处敬请原谅,毕竟写一篇文章也不是那么容易,我只是想看看到底能帮助到多少人,谢谢理解!
#include<iostream>
#include
<fstream>
#include
<vector>
#include
<random>
#include
<time.h>
#include
<string.h>
using namespace std;
const int maxNum=0x1<<30;
const int repeatMax=100;//控制迭代的上限,这里主要从效率的角度来考虑。一般来说迭代50--100次就能达到很好的效果
const int AttributeCount=2;//数据属性维度.
const int ClusterK=8;//聚成的簇的数量
typedef double AttributeType;
struct Object{//数据项的数据结构
AttributeType attribute[AttributeCount];
};
vector
<Object> allObj;//保存所有的数据
Object cluster[1000][ClusterK];//各个簇的数据项,这里假定每个簇的最大量为1000了,可以写成vector的数据结构,
Object oldcenter[ClusterK];//旧的各个中心点
int oldCluObjNum[ClusterK];//旧的各个簇有多少数据量
Object center[ClusterK];//对比旧的中心点
int CluObjNum[ClusterK];//对比旧的各簇的数据量
void getAllobject(ifstream &ifs);//加载所有数据
void kmeans(ifstream &ins);//算法
void produceData(string fileName,int maxNum,int objectNum);//随机产生数据,fileName文件名,maxNum数据的最大数,objectNum数据个数
int cloestCluster(Object obj);//返回当前数据项与哪个簇最近
void initCenter();//初始化各中心点
void updateCluster(int cluK,Object obj);//更新簇结构
bool isChange();//判断迭代之后中心点是否改变,若没有改变可以迭代结束了,得到局部最优解
void copyCenter();//复制到旧的中
void computeCenter();//重新计算中心点
AttributeType Distance(Object obj,Object obj2);//计算两个点之间的距离
int main(){
//produceData("data2.txt",100,50);
ifstream ifs;
ifs.open(
"data2.txt");
kmeans(ifs);
ifs.close();
system(
"pause");
}

void kmeans(ifstream &ins){
getAllobject(ins);
initCenter();
for(int i=0;i<ClusterK;i++){
center
=allObj;
CluObjNum
=0;
}
int repeat=0;
while(isChange()&&repeat<repeatMax){//阅读更多内容

2014年4月27日星期日

ipad中的“touchend”、"scroll"与"setTimeout" - 梦1106

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
ipad中的"touchend"、"scroll"与"setTimeout" - 梦1106  阅读原文»

在移动端,正常的一次swipe动作会依照以下顺序触发事件:

touchstart -> touchmove -> touchend ->scroll

在ipade中,touchend事件在手指离开时触发,由于是swipe动作,所以在手指离开后,屏幕还会滚动一段时间,直至最后停止,在最后的停止事件会触发scroll事件。

使用以下测试代码,一次swipe从touchend到scroll的时间大概经过0-2000ms不等(也许可能更长,依据加速度)

     var timestart =0;
$(window).on(
'scroll',function(){
console.log
(’-----scrollend:' + (new Date() - timestart) +'ms');
});
$(window).on(
'touchend',function(){
timestart
= new Date();
console.log(
'touchend');
})

现在向touchend中添加setTimeout事件,设定延迟时间为1ms(几乎一定在scroll之前)。

var timestart =0;
var timer = null;
function log(){
console.log(
"settimeout");
}
$(window).on(
'scroll',function(){
console.log(‘
-----scrollend:' + (new Date() - timestart) +'ms');
});
$(window).on(
'touchend',function(){
timestart = new Date();
console.log(
'touchend');
timer = setTimeout(log,1);
})

实验了四次,得到结果如下(使用weinre远程调试)

可以从结果中看到,settimeout并没有如预想的在scrollend之前触发,反而在scrollend触发后才触发。

由这种情况可以推测,事件队列中的顺序为 touchend回调 -> scroll回调 -> settimeout函数。

所以如果想操作touchend到scroll这段时间的动作,在ipad下是不可实现的。


本文链接:ipad中的"touchend"、"scroll"与"setTimeout",转载请注明。

简单易懂的程序语言入门小册子(6):基于文本替换的解释器,引入continuation - 古霜卡比  阅读原文»

当我写到这里的时候,我自己都吃了一惊。 环境、存储这些比较让人耳熟的还没讲到,continuation先出来了。 维基百科里对continuation的翻译是“延续性”。 这翻译看着总有些违和感而且那个条目也令人不忍直视。 总之continuation似乎没有好的中文翻译,仿佛中国的计算机科学里没有continuation这个概念似的。

Continuation这个概念相当于过程式语言里的函数调用栈。 它是用于保存“现在没空处理,待会再处理的事”的数据结构。 这样说有点抽象,举个例子,函数应用那条表达式的求值过程(call-by-value)是这样: \begin{equation*}\begin{array}{lcl} eval((M \; N)) &=& eval(L[X \leftarrow eval(N)]) \\ && \text{其中} eval(M) = \lambda X.L \end{array}\end{equation*}这个过程依次做这三件事:

  1. 计算$eval(M)$,结果是$\lambda X.L$,
  2. 计算$eval(N)$,
  3. 做替换$L[X \leftarrow eval(N)]$。

解释器一次只能计算一个表达式,所以当它计算$eval(M)$前,要先把第二步和第三步要做的事备忘到continuation。

假设$M$还是个函数调用$M=(M_1 \; M_2)$。 那么,计算$eval(M)$又要分三步: 先计算$eval(M_1)=\lambda X.L_1$,第二步计算$eval(M_2)$,第三步做替换$L_1[X \leftarrow eval(M_2)]$。 解释器只能先计算$eval(M_1)=\lambda X.L_1$,将第二步计算$eval(M_2)$,第三步做替换$L_1[X \leftarrow eval(M_2)]$备忘到continuation。 于是,continuation备忘的事情按待处理的顺序依次是:

  1. 计算$eval(M_2)$,
  2. 做替换$L_1[X \leftarrow eval(M_2)]$。
  3. 计算$eval(N)$,
  4. 做替换$L[X \leftarrow eval(N)]$。

可以看到,continuation是一个FILO(先进后出)的数据结构,也就是栈。

在之前的解释器里并没有提到continuation,但是解释器仍然能正常工作, 这是因为解释这个解释器的解释器——Racket解释器——帮我们管理了continuation。 这一节的目标是自己管理continuation。

从一个简单的递归函数做起

先说一个概念:尾调用。 假设一个函数体中有一句函数调用表达式$(f \; n)$,这个函数调用被称为尾调用,如果这条表达式是函数体里最后求值的表达式。 如$\lambda n.(f \; n)$,和$\lambda n.({if} \; ({iszero} \; n) \; 0 \; (f \; n))$中的$(f \; n)$都是尾调用。 而$\lambda n.(+ \; 1 \; (f \; n))$中的$(f \; n)$不是尾调用,因为计算完$(f \; n)$后还要再算个加法。 一个简单的判断是否尾调用的方法是看这条调用表达式是不是不在一个参数位置(let表达式和if表达式先做宏展开)。

学过C或者C++都知道,调用函数的时候是要保存信息到函数调用栈的(我上学时学的这俩,不知道其他语言的课上会不会讲函数调用栈)。 尾调用的特点是:尾调用理论上不需要保存信息到函数调用栈——实际上也不需要,但是有些语言就不支持,比如说Python。 换句话说,尾调用不会导致continuation增长。 这个很好理解,因为尾调用是最后求值的表达式了,不需要备忘后面要做的事(后面没有事了),所以也就不会导致continuation增长。 后面会从continuation的角度说明为什么尾调用不会令continuation增长。

题外话: 刚才提到“理论上”和“实际上”。 经常能听到这种句式:理论上怎么怎么,可惜,实际上是吧啦吧啦。 其中“吧啦吧啦”是一句对“怎么怎么”的否定。 我觉得这是反科学以及读书无用论的潜意识在作祟,另外有时候是用来逃避责任的借口。 理论上怎么样,实际上就应该怎么样。 如果有套理论的结论和现实的结果不同,那么这就不能称为理论,最多算个猜想,而且是个错误的猜想。

如果一个尾调用是一个递归调用,那么就称为尾递归。 尾递归又叫迭代。 我们现在要做的事其实就是把一个递归程序(之前写的解释器)中的非尾递归全改成尾递归, 也就是递归转迭代

为了熟悉递归转迭代的套路,先拿一个简单的递归函数练练手。 这个函数就是之前用到的double函数: \begin{equation*}\begin{array}{lcl} double(0) &=& 0 \\ double(n) &=& 2 + double(n-1), \text{其中} n \neq 0 \end{array}\end{equation*} 计算double函数的过程有一个状态量:当前计算的表达式$double(n)$或者一个数字$n$(计算结果)。 现在加入另一个状态量continuation,记为$\kappa$(因为continuation第一个字母c发音k,所以用了个长的像k的希腊字母……)。 计算double函数的过程只有第二行是递归过程,备忘的事是加2。 $\kappa$定义为: \begin{equation*}\begin{array}{lcl} \kappa &=& {mt} \\ &|& \left<\kappa, +2\right> \end{array}\end{equation*} mt表示空的continuation,也就是说没有后续的事情了。

加入continuation后的求值过程如下: \begin{equation*}\begin{array}{lcl} \left<double(0), \kappa\right>_v &\rightarrow_{v}& \left<0, \kappa\right>_c \\ \left<double(n), \kappa\right>_v &\rightarrow_{v}& \left<double(m), \left<\kappa, +2\right>\right>_v \\ && \text{其中} n \neq 0, m = n - 1 \\ \left<n, \left<\kappa, +2\right>\right>_c &\rightarrow_{c}& \left<m, \kappa\right>_c \\ && \text{其中} m = n + 2 \\ \left<n, {mt}\right>_c &\rightarrow_{c}& \text{输出} n \end{array}\end{equation*} 下面解释一下。 计算开始时的状态表示为$\left<double(n), {mt}\right>_v$。 下标v表示第一个状态量是一个表达式,要对这个表达式求值。 用箭头$\rightarrow$表示一步,带下标v的箭头$\rightarrow_v$表示这一步对表达式求值, 带下标c的箭头$\rightarrow_c$表示这一步从continuation中取出一件备忘的事执行。 对于$n \neq 0$,$\left<double(n), \kappa\right>_v$的下一步要做的是,计算$double(n-1)$,同时将加2备忘到$\kappa$, 也就是$\left<double(m), \left<\kappa, +2\right>\right>_v$,其中$m=n-1$。 当$n = 0$时,$double(0)$求得值$0$,所以$\left<double(0), \kappa\right>_v \rightarrow_{v} \left<0, \kappa\right>_c$。 用下标c表示第一个状态是一个数字,下一步该从continuation取出备忘的事来办了。 最后是$\left<n, \kappa\right>_c$的情况,如果$\kappa$不是空:$\kappa=\left<\kappa',+2\right>$,就加2到$n$上; 如果$\kappa$是空:$\kappa={mt}$,说明continuation没事了,而这时表达式也求完了,于是返回最终结果$n$。

然后是写代码。 针对$\rightarrow_v$和$\rightarrow_c$需要两个函数。 函数value-of/k是$\rightarrow_v$(Lisp命名规范里一般用斜杠表示with的意思)。 函数apply-cont是$\rightarrow_c$。

double1

double2

上面代码中用Lisp里的list数据结构来保存continuation。 我们可以不用list来保存continuation。 Continuation备忘的是“待做的事”。 这个“待做的事”可以理解为一个过程,也就是一个函数。 所以,可以用函数来保存continuation!

空mt是一个直接返回参数的函数(lambda (v) v)。 $\left<\kappa, +2\right>$先加2,然后应用$\kappa$:(lambda (v) (apply-cont cont v)),其中cont是$\kappa$。 完整代码:

double-proc

用函数来保存continuation的写法看起来蛮像回调函数(callback)。 Lisp的一个噱头是程序与数据统一对待,这也算是一个体现吧。 用函数还能实现对象(面向对象编程的对象),这是题外话了。 用函数保存数据一个好处是熟悉这种方法后写起来很方便; 坏处是扩展访问方式比较麻烦,并且调试的时候不能打印详细信息。

顺便再说一下,这种带着一个continuation当参数传来传去的代码风格叫continuation passing style,也就是传说中的CPS。 将一段不带continuation的代码转换成continuation passing style的过程叫CPS变换。 (更准确的说,CPS变换是指将代码中的非尾调用转换成尾调用。)


本文链接:简单易懂的程序语言入门小册子(6):基于文本替换的解释器,引入continuation,转载请注明。

阅读更多内容

2014年4月25日星期五

关于移动,爱游,联通三家运营商付费SDK的融合方案 - 诺亚行者

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
关于移动,爱游,联通三家运营商付费SDK的融合方案 - 诺亚行者  阅读原文»

第一次做付费SDK嵌入,所以如果有错误的地方请大家指出来。

付费SDK无非是这么两个流程:初始化》》付费。

初始化方面,虽然移动的SDK和其他两家有点不太一样,但也无妨,需要的东西都一样:都需要Context参数,附加应用AppID,AppKey。

而付费,则比较相似,都是通过传递payCode,Context作为参数。

因此,可以分离出一个借口:init,order

具体代码如下:

然后再分别实现三家运营商的SDK:

联通的:

爱游:

移动的,这个比较麻烦,只贴出核心代码,其他代码参考SDK demo:

然后是order的:

最后,在想要调用的activity中声明一个IConstructor,根据运营商进行选择初始化相关的运营商sdk,应该这么写:

---------------------

最后附上源码:

http://pan.baidu.com/s/1jGuUz6A


本文链接:关于移动,爱游,联通三家运营商付费SDK的融合方案,转载请注明。

基于ARP的局域网IP劫持――C语言实现 - 燕云  阅读原文»

我站在 烈烈风中

恨不能 荡尽绵绵心痛

望苍天 四方云动

剑在手

问天下谁是英雄

——《霸王别姬》

阅读这篇文章之前,请确认已经熟悉ARP报文伪造的方法,可参考《ARP数据包伪造》。

请看下图,这是全篇文章的鸟瞰:

要想实现上图的工作流程,必须实现两个模块:

•自由的伪造ARP报文

•抓取并分析所有流经网卡的数据包

从上图中可以看出,我们可以通过BPF或者DLPI层实现数据包的抓取分析,而tcpdump的根基——libpcap库,正是对BPF层的二次封装实现的C库,我们将通过它来实现数据包的抓取分析。

关于libpcap的基础使用,请参考这篇文章《libpcap使用》。

下面给出一个简单的libpcap过滤抓包的程序:

1 #include <pcap.h>
2 #include <time.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 unsigned char glTargetIP[4]={192,168,1,99};
7 char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
8 unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
9 char * glNICStr="eth2";
10
11 void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
12 {
13 int * id = (int *)arg;
14 unsigned char * src_ip =glTargetIP;
15 unsigned char * src_mac=glRetargetMac;
16 unsigned char * dst_ip =packet+28;
17 unsigned char * dst_mac=packet+22;
18
19 printf("id: %d\n", ++(*id));
20 printf("Packet length: %d\n", pkthdr->len);
21 printf("Number of bytes: %d\n", pkthdr->caplen);
22 printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
23
24 int i;
25 for(i=0; i<pkthdr->len; ++i)
26 {
27 printf(" %02x", packet);
28 if( (i + 1) % 16 == 0 )
29 {
30 printf("\n");
31 }
32 }
33
34 printf("\n\n");
35 }
36
37 int main ()
38 {
39 char errBuf[PCAP_ERRBUF_SIZE], * devStr;
40 struct bpf_program filter;
41
42 /* get a device */
43 devStr = pcap_lookupdev(errBuf);
44
45 if(devStr)
46 {
47 printf("success: device: %s\n", devStr);
48 }
49 else
50 {
51 printf("error: %s\n", errBuf);
52 exit(