在Linux终端:export LANG=GBK;
在SecureCRT字符设置:默认
上传:gbk编码,和utf8编码都没有乱码问题。。。


在Linux终端:export LANG=en_US.utf8;
在SecureCRT字符设置:默认
上传:gbk编码,和utf8!   utf8 编码都没有乱码,但是gbk有问题。


最好是第一种为好,两种情况显示都ok。。。其余设置都有乱码问题,舍弃!

有人这样setting:
使用SecreCRT远程访问中文版Linux主机时,对于中文显示会有乱码。
设置SecureCRT设置:选项(Options)->会话选项(Session Options)->外观(Appearance)->字符(Character),选择UTF-8。

我的系统是 LANG="en_US.UTF-8",改完SecureCRT设置重新登录即可.

通常就可以了,因为Linux默认LANG就是UTF-8。如果不是,则设置一下/etc/sysconfig/i18n,将LANG设置支持UTF-8。
[root@localhost sysconfig]# more i18n
LANG="zh_CN.UTF-8"
SUPPORTED="zh_CN.UTF-8:zh_CN:zh:en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"

重新登录就可以了!
之前我在一篇文章里面讲到把故人居网站升级为UTF8字符集,看过的也知道一些有关PHP和MySQL字符集的问题,通常情况下MySQL默认使用的字符集是latin1,如果我们的系统要使用utf8或者别的字符集,就需要对MySQL进行配置,并且在PHP程序中做一点处理,大致的方法如下:

1.修改my.ini (或者my.cnf)文件,在文件的[mysqld]中加入下面一行
character_set_server = utf8

由于MySQL的字符集和连接校对有分级,分别是操作系统级、数据库服务器级、数据库客户端级,这几个级别是从上往下包含的,我上面的那一行 character_set_server 参数实际上就是设置了全局的字符集,这样不管是MySQL数据存储、数据连接、结果返回都将是utf8,当然,如果您愿意,您也可以进行分别的设置,比如做如下设置
default-character-set = utf8
default-collation = utf8_general_ci
这样的设置可以设置一个默认字符集,在您的应用中如果没有特殊指定字符集,那将默认使用utf8作为字符集,并且使用utf8_general_ci作为连接校对的默认字符集;

简单的处理方法就是如我前面的那样,加入一行即可。

2.PHP程序中连接MySQL的时候,或者在执行mysql_query的时候,执行以下一行SQL语句
SET NAMES utf8
就是说在执行mysql_query之前,或者在完成mysql_connect()之后,执行 mysql_query(”SET NAMES utf8)

  有了前面的两个处理,您就可以正常的进行utf8字符集的数据库操作,不管在页面显示还是数据库中,字符都不会出现乱码。

  前面说到的方法是以前用到的常用方法,最近在MySQL的官方发现了这样一个参数 init_connect ,它的意思呢就是在MySQL启动的时候,自动执行init_connect 参数里面的SQL语句,支持用分号间隔的多个语句,于是我们可以把 SET NAMES utf8语句加到my.ini文件里面,在PHP程序里面就不用单独处理了,加入参数的方法很简单,就是在my.ini文件的 [mysqld] 段加入下面一行
init_connect = ‘SET NAMES utf8′

  不过这个方法有一个需要注意的地方,那就是该参数对于连接数据库的用户是超级用户组的用户将被忽略,那么在PHP程序中用来连接MySQL数据库的用户不能是SUPER组的用户,比如root用户就肯定不行,这样是为了避免该参数导致数据库致命错误,而无法使用任何一个用户连接上修改该项配置,之前我搞了两天都没有发现这样的问题,害我郁闷了很久。。。

有关MySQL的配置文件中用到的参数可以参考官方的文档 : http://dev.mysql.com/doc/refman/4.1/en/server-system-variables.html

  呵呵,让人又爱又恨的MySQL!
注意:
    出现你这样的原因是虽然你的WP设置了使用utf8,但是PHP在进行数据库连接的时候并没有使用utf8连接校验,这样插入到里面的数据存储方式虽然是 utf8,但是数据本身并不是utf8的,PHP读出来的时候使用的方法和插入一样,所以WP里面看到的并不会是乱码,相反在更加聪明的 phpmyadmin里面却看到了乱码,因为它使用了正确的utf8连接校验。

#!/bin/sh
#
# Created by xiangdong#
# To determine whether slave is running or not.
echo "Enter your Username"
read USERNAME
echo "Enter your password"
stty -echo
read PASSWD
stty echo
RESULT=`mysql -h10.69.3.198 -P4406 -u$USERNAME -p$PASSWD -A relation < sql_in.txt > sql_data_out.  
txt`

http://blog.chinaunix.net/u/29134/showart_970894.html

#!/bin/bash
# Tetris Game
# 10.21.2003 xhchen

#颜色定义
cRed=1
cGreen=2
cYellow=3
cBlue=4
cFuchsia=5
cCyan=6
cWhite=7
colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)

#位置和大小
iLeft=3
iTop=2
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))

#颜色设置
cBorder=$cGreen
cScore=$cFuchsia
cScoreValue=$cCyan

#控制信号
#改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;
#当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。
sigRotate=25
sigLeft=26
sigRight=27
sigDown=28
sigAllDown=29
sigExit=30

#七中不同的方块的定义
#通过旋转,每种方块的显示的样式可能有几种
box0=(0 0 0 1 1 0 1 1)
box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)
#所有其中方块的定义都放到box变量中
box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
#各种方块旋转后可能的样式数目
countBox=(1 2 2 2 4 4 4)
#各种方块再box数组中的偏移
offsetBox=(0 1 3 5 7 11 15)

#每提高一个速度级需要积累的分数
iScoreEachLevel=50 #be greater than 7

#运行时数据
sig=0 #接收到的signal
iScore=0 #总分
iLevel=0 #速度级
boxNew=() #新下落的方块的位置定义
cBoxNew=0 #新下落的方块的颜色
iBoxNewType=0 #新下落的方块的种类
iBoxNewRotate=0 #新下落的方块的旋转角度
boxCur=() #当前方块的位置定义
cBoxCur=0 #当前方块的颜色
iBoxCurType=0 #当前方块的种类
iBoxCurRotate=0 #当前方块的旋转角度
boxCurX=-1 #当前方块的x坐标位置
boxCurY=-1 #当前方块的y坐标位置
iMap=() #背景方块图表

#初始化所有背景方块为-1, 表示没有方块
for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done


#接收输入的进程的主函数
function RunAsKeyReceiver()
{
local pidDisplayer key aKey sig cESC sTTY

pidDisplayer=$1
aKey=(0 0 0)

cESC=`echo -ne "\33"`
cSpace=`echo -ne "\40"`

#保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。
#如果在read -s时程序被不幸杀掉,可能会导致终端混乱,
#需要在程序退出时恢复终端属性。
sTTY=`stty -g`

#捕捉退出信号
trap "MyExit;" INT TERM
trap "MyExitNoSub;" $sigExit

#隐藏光标
echo -ne "\33[?25l"


while (( 1 ))
do
#读取输入。注-s不回显,-n读到一个字符立即返回
read -s -n 1 key

aKey[0]=${aKey[1]}
aKey[1]=${aKey[2]}
aKey[2]=$key
sig=0

#判断输入了何种键
if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
then
#ESC键
MyExit
elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]
then
if [[ $key == "A" ]]; then sig=$sigRotate #<向上键>
elif [[ $key == "B" ]]; then sig=$sigDown #<向下键>
elif [[ $key == "D" ]]; then sig=$sigLeft #<向左键>
elif [[ $key == "C" ]]; then sig=$sigRight #<向右键>
fi
elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate #W, w
elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown #S, s
elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft #A, a
elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight #D, d
elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown #空格键
elif [[ $key == "Q" || $key == "q" ]] #Q, q
then
MyExit
fi

if [[ $sig != 0 ]]
then
#向另一进程发送消息
kill -$sig $pidDisplayer
fi
done
}

#退出前的恢复
function MyExitNoSub()
{
local y

#恢复终端属性
stty $sTTY
((y = iTop + iTrayHeight + 4))

#显示光标
echo -e "\33[?25h\33[${y};0H"
exit
}


function MyExit()
{
#通知显示进程需要退出
kill -$sigExit $pidDisplayer

MyExitNoSub
}


#处理显示和游戏流程的主函数
function RunAsDisplayer()
{
local sigThis
InitDraw

#挂载各种信号的处理函数
trap "sig=$sigRotate;" $sigRotate
trap "sig=$sigLeft;" $sigLeft
trap "sig=$sigRight;" $sigRight
trap "sig=$sigDown;" $sigDown
trap "sig=$sigAllDown;" $sigAllDown
trap "ShowExit;" $sigExit

while (( 1 ))
do
#根据当前的速度级iLevel不同,设定相应的循环的次数
for ((i = 0; i < 21 - iLevel; i++))
do
sleep 0.02
sigThis=$sig
sig=0

#根据sig变量判断是否接受到相应的信号
if ((sigThis == sigRotate)); then BoxRotate; #旋转
elif ((sigThis == sigLeft)); then BoxLeft; #左移一列
elif ((sigThis == sigRight)); then BoxRight; #右移一列
elif ((sigThis == sigDown)); then BoxDown; #下落一行
elif ((sigThis == sigAllDown)); then BoxAllDown; #下落到底
fi
done
#kill -$sigDown $$
BoxDown #下落一行
done
}


#BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以
function BoxMove()
{
local j i x y xTest yTest
yTest=$1
xTest=$2
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + yTest))
((x = ${boxCur[$i]} + xTest))
if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
then
#撞到墙壁了
return 1
fi
if ((${iMap[y * iTrayWidth + x]} != -1 ))
then
#撞到其他已经存在的方块了
return 1
fi
done
return 0;
}


#将当前移动中的方块放到背景方块中去,
#并计算新的分数和速度级。(即一次方块落到底部)
function Box2Map()
{
local j i x y xp yp line

#将当前移动中的方块放到背景方块中去
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + boxCurY))
((x = ${boxCur[$i]} + boxCurX))
((i = y * iTrayWidth + x))
iMap[$i]=$cBoxCur
done

#消去可被消去的行
line=0
for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
do
for ((i = j + iTrayWidth - 1; i >= j; i--))
do
if ((${iMap[$i]} == -1)); then break; fi
done
if ((i >= j)); then continue; fi

((line++))
for ((i = j - 1; i >= 0; i--))
do
((x = i + iTrayWidth))
iMap[$x]=${iMap[$i]}
done
for ((i = 0; i < iTrayWidth; i++))
do
iMap[$i]=-1
done
done

if ((line == 0)); then return; fi

#根据消去的行数line计算分数和速度级
((x = iLeft + iTrayWidth * 2 + 7))
((y = iTop + 11))
((iScore += line * 2 - 1))
#显示新的分数
echo -ne "\33[1m\33[3${cScoreValue}m\33[${y};${x}H${iScore} "
if ((iScore % iScoreEachLevel < line * 2 - 1))
then
if ((iLevel < 20))
then
((iLevel++))
((y = iTop + 14))
#显示新的速度级
echo -ne "\33[3${cScoreValue}m\33[${y};${x}H${iLevel} "
fi
fi
echo -ne "\33[0m"


#重新显示背景方块
for ((y = 0; y < iTrayHeight; y++))
do
((yp = y + iTrayTop + 1))
((xp = iTrayLeft + 1))
((i = y * iTrayWidth))
echo -ne "\33[${yp};${xp}H"
for ((x = 0; x < iTrayWidth; x++))
do
((j = i + x))
if ((${iMap[$j]} == -1))
then
echo -ne " "
else
echo -ne "\33[1m\33[7m\33[3${iMap[$j]}m\33[4${iMap[$j]}m[]\33[0m"
fi
done
done
}


#下落一行
function BoxDown()
{
local y s
((y = boxCurY + 1)) #新的y坐标
if BoxMove $y $boxCurX #测试是否可以下落一行
then
s="`DrawCurBox 0`" #将旧的方块抹去
((boxCurY = y))
s="$s`DrawCurBox 1`" #显示新的下落后方块
echo -ne $s
else
#走到这儿, 如果不能下落了
Box2Map #将当前移动中的方块贴到背景方块中
RandomBox #产生新的方块
fi
}

#左移一列
function BoxLeft()
{
local x s
((x = boxCurX - 1))
if BoxMove $boxCurY $x
then
s=`DrawCurBox 0`
((boxCurX = x))
s=$s`DrawCurBox 1`
echo -ne $s
fi
}

#右移一列
function BoxRight()
{
local x s
((x = boxCurX + 1))
if BoxMove $boxCurY $x
then
s=`DrawCurBox 0`
((boxCurX = x))
s=$s`DrawCurBox 1`
echo -ne $s
fi
}


#下落到底
function BoxAllDown()
{
local k j i x y iDown s
iDown=$iTrayHeight

#计算一共需要下落多少行
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + boxCurY))
((x = ${boxCur[$i]} + boxCurX))
for ((k = y + 1; k < iTrayHeight; k++))
do
((i = k * iTrayWidth + x))
if (( ${iMap[$i]} != -1)); then break; fi
done
((k -= y + 1))
if (( $iDown > $k )); then iDown=$k; fi
done

s=`DrawCurBox 0` #将旧的方块抹去
((boxCurY += iDown))
s=$s`DrawCurBox 1` #显示新的下落后的方块
echo -ne $s
Box2Map #将当前移动中的方块贴到背景方块中
RandomBox #产生新的方块
}


#旋转方块
function BoxRotate()
{
local iCount iTestRotate boxTest j i s
iCount=${countBox[$iBoxCurType]} #当前的方块经旋转可以产生的样式的数目

#计算旋转后的新的样式
((iTestRotate = iBoxCurRotate + 1))
if ((iTestRotate >= iCount))
then
((iTestRotate = 0))
fi

#更新到新的样式, 保存老的样式(但不显示)
for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
do
boxTest[$j]=${boxCur[$j]}
boxCur[$j]=${box[$i]}
done

if BoxMove $boxCurY $boxCurX #测试旋转后是否有空间放的下
then
#抹去旧的方块
for ((j = 0; j < 8; j++))
do
boxCur[$j]=${boxTest[$j]}
done
s=`DrawCurBox 0`

#画上新的方块
for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
do
boxCur[$j]=${box[$i]}
done
s=$s`DrawCurBox 1`
echo -ne $s
iBoxCurRotate=$iTestRotate
else
#不能旋转,还是继续使用老的样式
for ((j = 0; j < 8; j++))
do
boxCur[$j]=${boxTest[$j]}
done
fi
}


#DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。
function DrawCurBox()
{
local i j t bDraw sBox s
bDraw=$1

s=""
if (( bDraw == 0 ))
then
sBox="\40\40"
else
sBox="[]"
s=$s"\33[1m\33[7m\33[3${cBoxCur}m\33[4${cBoxCur}m"
fi

for ((j = 0; j < 8; j += 2))
do
((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
#\33[y;xH, 光标到(x, y)处
s=$s"\33[${i};${t}H${sBox}"
done
s=$s"\33[0m"
echo -n $s
}


#更新新的方块
function RandomBox()
{
local i j t

#更新当前移动的方块
iBoxCurType=${iBoxNewType}
iBoxCurRotate=${iBoxNewRotate}
cBoxCur=${cBoxNew}
for ((j = 0; j < ${#boxNew[@]}; j++))
do
boxCur[$j]=${boxNew[$j]}
done


#显示当前移动的方块
if (( ${#boxCur[@]} == 8 ))
then
#计算当前方块该从顶端哪一行"冒"出来
for ((j = 0, t = 4; j < 8; j += 2))
do
if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
done
((boxCurY = -t))
for ((j = 1, i = -4, t = 20; j < 8; j += 2))
do
if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi
if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
done
((boxCurX = (iTrayWidth - 1 - i - t) / 2))

#显示当前移动的方块
echo -ne `DrawCurBox 1`

#如果方块一出来就没处放,Game over!
if ! BoxMove $boxCurY $boxCurX
then
kill -$sigExit ${PPID}
ShowExit
fi
fi



#清除右边预显示的方块
for ((j = 0; j < 4; j++))
do
((i = iTop + 1 + j))
((t = iLeft + 2 * iTrayWidth + 7))
echo -ne "\33[${i};${t}H "
done

#随机产生新的方块
((iBoxNewType = RANDOM % ${#offsetBox[@]}))
((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]}))
for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++))
do
boxNew[$j]=${box[$i]};
done

((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]}))

#显示右边预显示的方块
echo -ne "\33[1m\33[7m\33[3${cBoxNew}m\33[4${cBoxNew}m"
for ((j = 0; j < 8; j += 2))
do
((i = iTop + 1 + ${boxNew[$j]}))
((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]}))
echo -ne "\33[${i};${t}H[]"
done
echo -ne "\33[0m"
}


#初始绘制
function InitDraw()
{
clear
RandomBox #随机产生方块,这时右边预显示窗口中有方快了
RandomBox #再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落
local i t1 t2 t3

#显示边框
echo -ne "\33[1m"
echo -ne "\33[3${cBorder}m\33[4${cBorder}m"

((t2 = iLeft + 1))
((t3 = iLeft + iTrayWidth * 2 + 3))
for ((i = 0; i < iTrayHeight; i++))
do
((t1 = i + iTop + 2))
echo -ne "\33[${t1};${t2}H||"
echo -ne "\33[${t1};${t3}H||"
done

((t2 = iTop + iTrayHeight + 2))
for ((i = 0; i < iTrayWidth + 2; i++))
do
((t1 = i * 2 + iLeft + 1))
echo -ne "\33[${iTrayTop};${t1}H=="
echo -ne "\33[${t2};${t1}H=="
done
echo -ne "\33[0m"


#显示"Score"和"Level"字样
echo -ne "\33[1m"
((t1 = iLeft + iTrayWidth * 2 + 7))
((t2 = iTop + 10))
echo -ne "\33[3${cScore}m\33[${t2};${t1}HScore"
((t2 = iTop + 11))
echo -ne "\33[3${cScoreValue}m\33[${t2};${t1}H${iScore}"
((t2 = iTop + 13))
echo -ne "\33[3${cScore}m\33[${t2};${t1}HLevel"
((t2 = iTop + 14))
echo -ne "\33[3${cScoreValue}m\33[${t2};${t1}H${iLevel}"
echo -ne "\33[0m"
}


#退出时显示GameOVer!
function ShowExit()
{
local y
((y = iTrayHeight + iTrayTop + 3))
echo -e "\33[${y};0HGameOver!\33[0m"
exit
}



#游戏主程序在这儿开始.
if [[ $1 != "--show" ]]
then
bash $0 --show& #以参数--show将本程序再运行一遍
RunAsKeyReceiver $! #以上一行产生的进程的进程号作为参数
exit
else
#当发现具有参数--show时,运行显示函数
RunAsDisplayer
exit
fi

select FQQ,FScoreCount from Tbl_User into outfile "/tmp/terminatedtest.txt" fields terminated by ",";



http://blog.chinaunix.net/u/29134/showart_1074828.html


select * into destTbl from srcTbl
insert into destTbl(fld1, fld2) select fld1, 5 from srcTbl
以上两句都是将 srcTbl 的数据插入到 destTbl,但两句又有区别的:

•第一句(select into from)要求目标表(destTbl)不存在,因为在插入时会自动创建。
•第二句(insert into select from)要求目标表(destTbl)存在,由于目标表已经存在,所以我们除了插入源表(srcTbl)的字段外,还可以插入常量,如例中的:5。

mysql> select * into user_score_20090429  from user_score_20090430;
要求目标表( user_score_20090429  )不存在



insert into user_score_20090504 select * from user_score_20090505 where uid=1608843755;
//这个靠谱些验证过

ERROR 1062 (23000): Duplicate entry '67' for key 1
唯一键id冲突,那就:
truncate table `user_score_20090504`;


修改表名称(发现权限不够):

RENAME TABLE user_score_20090505 TO user_score_20090504;
   用文本方式将数据装入一个数据库表

  如果一条一条地输入,很麻烦。我们可以用文本文件的方式将所有记录加入你的数据库表中。创建一个文本文件“mysql.txt”,每行包含一个记录,用定位符(tab)把值分开,并且以在CREATE TABLE语句中列出的列次序给出,例如:

abccs f 1977-07-07 china   mary f 1978-12-12 usa tom m 1970-09-02 usa


使用下面命令将文本文件“mytable.txt”装载到mytable表中:mysql> LOAD DATA LOCAL INFILE "mytable.txt" INTO TABLE pet;

复制表
create table table2 select * from table1 limit 21;//也可以复制整个表。。。

如果需要的只是某些列也可以将*改为那些列的名字。
复制表的某些列也可以使用这样的方法:
create table b as select a.id, a.name, a.address from user a;
阅读全文
强制索引示例:
select  information.group, information.connection, information.productid, information.invitetype,relation.id, relation.owneruid, relation.otheruid, relation.type, relation.status, relation.infoid from relation  FORCE INDEX (oo,infoid) left join information   FORCE INDEX (g_i_c) on relation.infoid=information.infoid where information.group = 0 and relation.owneruid = 1257432324 and relation.type = 1;

强制不使用缓存查询示例:
select  SQL_NO_CACHE  information.group, information.connection, information.productid, information.invitetype,relation.id, relation.owneruid, relation.otheruid, relation.type, relation.status, relation.infoid from relation  FORCE INDEX (oo,infoid) left join information   FORCE INDEX (g_i_c) on relation.infoid=information.infoid where information.group = 0 and relation.owneruid = 1257432324 and relation.type = 1;


强制不使用索引示例:

select SQL_NO_CACHE  relation.id, relation.owneruid, relation.otheruid, relation.type, relation.status, relation.infoid, information.group, information.connection, information.productid, information.invitetype from relation IGNORE INDEX (PRIMARY,otc,oo,ots,uniq_key,infoid) left join information IGNORE INDEX (PRIMARY,g_i_c)  on relation.infoid=information.infoid where information.group = 0 and relation.owneruid = 1257432324 and relation.type = 1;


强制使用临时表:

select SQL_NO_CACHE SQL_BUFFER_RESULT  relation.id, relation.owneruid, relation.otheruid, relation.type, relation.status, relation.infoid, information.group, information.connection, information.productid, information.invitetype from relation left join information on relation.infoid=information.infoid where information.group = 0 and relation.owneruid = 1257432324 and relation.type = 1;


其他强制操作,优先操作如下:阅读全文
由于出现很多连接错误,主机'host_name'被屏蔽。 可使用'mysqladmin flush-hosts'解除屏蔽。
可使用'mysqladmin flush-hosts'解除屏蔽。

允许的中断连接请求的数目由max_connect_errors系统变量的值决定。当超出max_connect_errors规定的连接请求时,mysqld将认为某处出错(例如,某人正试图插入),并屏蔽主机的进一步连接请求,直至执行了mysqladmin flush-hosts命令,或发出了FLUSH HOSTS语句为止。

在默认情况下,mysqld会在10次连接错误后屏蔽主机。你可以通过下述方式启动服务器来调整该值:

shell> mysqld_safe --max_connect_errors=10000 &

如果在给定主机上遇到该错误,首先应核实该主机的TCP/IP连接是否正确。如果存在网络问题,增加max_connect_errors变量的值不会有任何好处。



GRANT ALL PRIVILEGES ON *.* TO 'space'@'%' IDENTIFIED BY '123qwe';
GRANT ALL PRIVILEGES ON *.* TO 'space'@'localhost' IDENTIFIED BY '123qwe';

只对某个库分配权限:
GRANT ALL ON DB_***team2010***.* TO kary@localhost IDENTIFIED BY "zu9UWep**";
FLUSH PRIVILEGES ;
mysql -ukary -pzu9UWepr


mysql -uspace -p123qwe  -P3306

最后,刷新:
FLUSH PRIVILEGES
http://www.linuxidc.com/Linux/2008-10/16760p2.htm
[ 起源 ]

Linux/Unix下守护进程(Daemon)大家都知道,比如我们常用的httpd、mysqld等等,就是常驻内存运行的程序,类似于Windows下的服务。一般守护进程都是使用C/C++来写,就是通过fork生成子进程,当前台shell下的父进程被杀掉,子进程就转到后台运行,为了不在终端产生输出信息,就通过 syslog等函数来写日志文件。

我们知道php是脚本语言,通过php的脚本引擎来执行,所以要做成守护进程比较麻烦,我们今天就来结合Unix/Linux的命令来实现我们守护进程的功能。

[ 原理 ]

Unix中的nohup命令的功能就是不挂断地运行命令,同时nohup把程序的所有输出到放到当前目录的nohup.out文件中,如果文件不可写,则放到<用户主目录>/nohup.out 文件中。那么有了这个命令以后,我们的php程序就写程shell脚本,使用循环来让我们的脚本一直运行,那么不管我们终端窗口是否关闭,都能够让我们的php脚本一直运行。当然,当我们的php进程被杀或者我们的操作系统重启了,自然就会中止了。

[ 功能 ]

肯定会问,让我们的php脚本做了守护进程又有什么用处呢?当然有,比如最典型的作用,能够基本的替代cron的功能,比如我们需要定期实行的某些操作,完全可以交给它来做,不再需要cron,当然,如果服务器重启就没有办法了,不过,一般的Unix服务器不是那么容易重启的。另外,我们还可以做一个简单的服务器端的功能,比如做一个能够Telnet过去的服务器,嘿嘿,可以做成一个小后门,不过这样实现稍微有点复

杂。


[ 实践 ]

例子一:自动生成文件

我们现在来做两个例子来证明我们上面的说法。首先第一个是每个三十秒自动生成一个文件,永远执行下去。

首必须确保操作系统是Unix或者Linux,比如可以是FreeBSD、Redhat、Fedora或者SUSE什么的。然后我们必须确保我们的php脚本引擎是在 /usr/local/php/bin/php,具体路径可以按照你实际路径来写,如果没有脚本引擎,请自行安装。

比如当前目录是 /home/heiyeluren/,那么我们使用vi或者其他编辑器编写一个叫做php_daemon1.php的文件:
$ vi php_daemon1.php

然后写入如下代码:

#! /usr/local/php/bin/php
<?
set_time_limit(0);
while(1)
{
@fopen("test_".time().".txt","w");
sleep(30);
}
?>


然后保存并且退出vi,然后赋予php_daemon1.php文件可执行权限:
$ chmod +x /home/heiyeluren/php_daemon1.php

然后再让我们的脚本再后台执行,执行如下命令:
$ nohup /home/heiyeluren/php_daemon1.php &

记得最后加上 & 符号,这样才能够跑到后台去运行,执行上述命令后出现如下提示:

[1] 82480
appending output to nohup.out

再 回后车后将出现shell提示符。那么上面的提示就是说,所有命令执行的输出信息都会放到 nohup.out 文件中,这个上面已经讲了。然后执行上面命令后,我们每个三十秒在当前目录就会看到多出以test_开头的文件,比如: test_1139901144.txt test_1139901154.txt等等文件,那么就证明我们的程序已经再后台运行了。

那么我们如何终止程序的运行呢?最好办法就是重启操作系统,呵呵,当然,这是不可取的,我们可以使用kill命令来杀掉这个进程,杀进程之前自然后知道进程的PID号,就是Process ID,使用ps命令就能够看到了。


$ ps
PID TT STAT      TIME COMMAND
82374 p3 Ss     0:00.14 -bash (bash)
82510 p3 S      0:00.06 /usr/local/php/bin/php /home/heiyeluren/php_daemon1.php
82528 p3 R+     0:00.00 ps


上面我们已经看到了我们的php的进程id是:82510 ,于是我们再执行kill命令:


$ kill -9 82510
[1]+ Killed                  nohup /home/heiyeluren/php_daemon1.php


看到这么提示就明白这个进程被杀了,再ps,就会发现没有了:

$ ps
PID TT STAT      TIME COMMAND
82374 p3 Ss     0:00.17 -bash (bash)
82535 p3 R+     0:00.00 ps

如果直接ps命令无法看到进程,那么就使用 ps & apos 两个结合命令来查看,一定能够看到进程。
再上面的基础上进程扩展,能够做成属于自己的cron程序,那就不需要cron啦,当然,这只是一种方式


例子二:服务器端的守护进程

这个例子跟网络有关,大致就是模拟使用php做服务器端,然后一直后台运行,达到服务器端Daemon的效果。

继续在我们的主目录下:/home/heiyeluren,编辑文件php_daemon2.php:


$ vi php_daemon2.php


输入如下代码(代码来自PHP手册,我进行了修改注释):


#! /usr/local/php/bin/php
<?php
/* 设置不显示任何错误 */
error_reporting(0);

/* 脚本超时为无限 */
set_time_limit(0);

/* 开始固定清除 */
ob_implicit_flush();

/* 本机的IP和需要开放的端口 */
$address = '192.168.0.1';
$port = 10000;

/* 产生一个Socket */
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
    echo "socket_create() failed: reason: " . socket_strerror($sock) . "\n";
}

/* 把IP地址端口进行绑定 */
if (($ret = socket_bind($sock, $address, $port)) < 0) {
    echo "socket_bind() failed: reason: " . socket_strerror($ret) . "\n";
}

/* 监听Socket连接 */
if (($ret = socket_listen($sock, 5)) < 0) {
    echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n";
}

/* 永远循环监接受用户连接 */
do {
    if (($msgsock = socket_accept($sock)) < 0) {
        echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
        break;
    }
    /* 发送提示信息给连接上来的用户 */
    $msg = "==========================================\r\n" .
" Welcome to the PHP Test Server. \r\n\r\n".
        " To quit, type 'quit'. \r\n" .
" To shut down the server type 'shutdown'.\r\n" .
" To get help message type 'help'.\r\n" .
"==========================================\r\n" .
"php> ";
    socket_write($msgsock, $msg, strlen($msg));

    do {
        if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
            echo "socket_read() failed: reason: " . socket_strerror($ret) . "\n";
            break 2;
        }
        if (!$buf = trim($buf)) {
            continue;
        }
   /* 客户端输入quit命令时候关闭客户端连接 */
        if ($buf == 'quit') {
            break;
        }
   /* 客户端输入shutdown命令时候服务端和客户端都关闭 */
        if ($buf == 'shutdown') {
            socket_close($msgsock);
            break 2;
        }
   /* 客户端输入help命令时候输出帮助信息 */
   if ($buf == 'help') {
    $msg = " PHP Server Help Message \r\n\r\n".
    " To quit, type 'quit'. \r\n" .
    " To shut down the server type 'shutdown'.\r\n" .
    " To get help message type 'help'.\r\n" .
    "php> ";
    socket_write($msgsock, $msg, strlen($msg));
    continue;
   }
   /* 客户端输入命令不存在时提示信息 */
        $talkback = "PHP: unknow command '$buf'.\r\nphp> ";
        socket_write($msgsock, $talkback, strlen($talkback));
        echo "$buf\n";
    } while (true);
    socket_close($msgsock);
} while (true);

/* 关闭Socket连接 */
socket_close($sock);
?>


保存以上代码退出。

上面的代码大致就是完成一个类似于Telnet服务器端的功能,就是当服务器端运行该程序的时候,客户端能够连接该服务器的10000端口进行通信。

加上文件的可执行权限:

$ chmod +x /home/heiyeluren/php_daemon2.php


在服务器上执行命令:

$ nohup /home/heiyeluren/php_daemon2.php &


就进入了后台运行,我们通过Windows的客户端telnet上去:


C:\>telnet 192.168.0.1 10000


如果提示:

正在连接到192.168.0.188...不能打开到主机的连接, 在端口 10000: 连接失败

则说明服务器端没有开启,或者上面的程序没有正确执行,请检查php是否 --enable-sockets 功能。如果提示:


==========================================
Welcome to the PHP Test Server.

To quit, type 'quit'.
To shut down the server type 'shutdown'.
To get help message type 'help'.
==========================================

php>


则说明顺利连接上了我们的PHP写的服务器端守护进程,在php>提示符后面能够执行help、quit、shutdown等三个命令,如果命令输入不是这三

个,则提示:


php> asdf
PHP: unknow command 'asdf'.

执行help命令可以获取帮助:

php> help
PHP Server Help Message

To quit, type 'quit'.
To shut down the server type 'shutdown'.
To get help message type 'help'.



这个服务器端就不介绍了,可以自行扩展。

杀进程跟例子一类似。

[ 总结 ]

通过以上学习,我们知道php也可以做守护进程,如果设计的好,功能也会比较强大,不过我们这里只是学习而已,可以自行研究更新。
本文参考了php中文手册,多看手册,对自己非常有好处
文件:
         a.php  b.php  
         aTest.php

a.php:


<?php
class a
{
  private $inHandle;
    public function getHandle($handle='')
    {  
        if ('' != $handle)
        {  
            $this->inHandle = $handle;
            return ;
        }  
        elseif ('' != $this->inHandle)
        {  
            return;
        }  
        $this->inHandle = new b();
        return;
    }
  public function use_b_class($num)
  {  //调用b类的:need_mock方法,假如是外部资源,为此需要mock
    $value = $this->inHandle->need_mock($num);
    $result = $value;
    return $result;    
  }  
}
?>



b.php



<?php
class b
{  protected $a = 0;
  protected $b = 0;
  public function __construct($a,$b)
  {
    $this->a = $a;
    $this->b = $b;
    echo $this->b;    
  }
  public function  need_mock($a)
  {
    $b = $this->a+$a;
    return $b;
  }
}
?>


aTest.php

<?php
require_once 'a.php';
require_once 'b.php';
require_once 'PHPUnit/Framework/TestCase.php';
/**
* a test case.
*/
class aTest extends PHPUnit_Framework_TestCase {  
  /**
   * @var a
   */
  private $a;  
  /**
   * Prepares the environment before running a test.
   */
  protected function setUp() {
    parent::setUp ();    
    // TODO Auto-generated aTest::setUp()
    $this->a = new a(/* parameters */);
  }  
  /**
   * Cleans up the environment after running a test.
   */
  protected function tearDown() {
    // TODO Auto-generated aTest::tearDown()
    $this->a = null;    
    parent::tearDown ();
  }
  
  /**
   * Constructs the test case.
   */
  public function __construct() {
    // TODO Auto-generated constructor
  }
  
  /**
   * Tests a->getHandle()
   */
  public function testGetHandle() {
    // TODO Auto-generated aTest->testGetHandle()
    $this->markTestIncomplete ( "getHandle test not implemented" );    
    $this->a->getHandle(/* parameters */);  
  }
  
  /**
   * Tests a->use_b_class()
   */
  public function testUse_b_class() {
    // TODO Auto-generated aTest->testUse_b_class()
    //$this->markTestIncomplete ( "use_b_class test not implemented" );
    
    //$this->a->use_b_class(/* parameters */);
    $a = array(1,"第二个参数");//注意:必须传array(构造函数参数1,构造函数参数2,构造函数参数3)
    $stub = $this->getMock('b', array('need_mock'),$a);
        $stub->expects($this->any())
             ->method('need_mock')
             ->with(      
                   $this->equalTo( 1 )//传入一个参数
                   )
             ->will($this->returnValue(11));//设定返回为11
        $this->a->getHandle($stub);//传入经过mock的对象      
        echo $this->a->use_b_class(1);
        $this->assertEquals($this->a->use_b_class(1) , 11 );
        $this->assertEquals(array(array(0,1,2)),array(array(0,1,2)));//必须是所谓的二维数组,否则出错
  
  }

}



程序:

1 接收程序


#include<REG51.h>



void init(void)
{
TMOD=0x20;
TH1=0xE8;
TL1=0xE8;
PCON=0x00;
TR1=1;
SCON=0x50;
}


void checkout(unsigned int para)
{   unsigned int paracheck=para;
redo:   if(SBUF!=paracheck)
        SBUF=0xFF;
     while(TI==0);
  TI=0;
  while(RI==0);
  RI=0;
        if(SBUF!=paracheck)
  goto redo;
  
      else SBUF=0xBB;
  while(TI==0);
  TI=0;



}


void ledflash(unsigned char flashnum)
{
   unsigned char i,k;
   for(i=flashnum;i>0;i--)
     for(k=200;k>0;k--)
  {
  ;
  P0=0x00;
  P0=0xFF;
     }
}



void get()
{  unsigned int getnum;
  while(RI==0);
  RI=0;
  while((getnum=SBUF)!=0xCC)
  {
  if(getnum%4==0)
    {ledflash(getnum);
       SBUF=0xBB;
    goto check;}
  else
     SBUF=0xFF;
check: while(TI==0);
  TI=0;
     while(RI==0);
      RI=0;
}

}





void ledon()
{
P0=0x00;
P0=0xFF;
}


void ledoff()
{
P0=0xFF;
P0=0x00;
}



void main(void)
{

while(1)
{
init();
checkout(0xAA);
ledon();
get();
checkout(0xCC);
ledoff();
}
}



2 发送程序


#include<REG51.h>






void init(void)
{
TMOD=0x20;
TH1=0xE8;
TL1=0xE8;
PCON=0x00;
TR1=1;
SCON=0x50;

}




void checkout(unsigned int para)
{   unsigned int paracheck;
           paracheck=para;
redo:      SBUF=paracheck;
     while(TI==0);
     TI=0;
     while(RI==0);
     RI=0;
     if(SBUF!=0xBB)
     goto redo;
}



void sent(void)
{unsigned char i;
      checkout(0xAA);

    
  
   for( i=0;i<20;i++)
    {
   if(i%4==0)
           checkout(i);
        }      

      checkout(0xCC);
}



void ledon(void)
{
P0=0x00;
P0=0xFF;

}

void ledoff(void)
{

P0=0x00;
}




void main()
{
while(1)
{
init();
ledon();
sent();
ledoff();
};


}

int openport(char *Dev) //打开串口

int setport(int fd, int baud,int databits,int stopbits,int parity)//设置串口,波特率,数据位,停止位,校验

int readport(int fd,char *buf,int len,int maxwaittime)//读数据,参数为串口,BUF,长度,超时时间

int writeport(int fd,char *buf,int len)  //发送数据

void clearport(int fd)      //如果出现数据与规约不符合,可以调用这个函数来刷新串口读写数据


#include   <stdio.h>  
#include   <string.h>  
#include   <unistd.h>  
#include   <fcntl.h>  
#include   <errno.h>  
#include   <termios.h>  
#include   <sys/time.h>
int openport(char *Dev)  
{
int fd = open( Dev, O_RDWR|O_NOCTTY|O_NDELAY );
if (-1 == fd)
{    
  perror("Can''t Open Serial Port");
  return -1;  
}
else
  return fd;

}  
  
int setport(int fd, int baud,int databits,int stopbits,int parity)
{
int baudrate;
struct   termios   newtio;  
switch(baud)
{
case 300:
  baudrate=B300;
  break;
case 600:
  baudrate=B600;
  break;
case 1200:
  baudrate=B1200;
  break;
case 2400:
  baudrate=B2400;
  break;
case 4800:
  baudrate=B4800;
  break;
case 9600:
  baudrate=B9600;
  break;
case 19200:
  baudrate=B19200;
  break;
case 38400:
  baudrate=B38400;
  break;
default :
  baudrate=B9600;  
  break;
}
tcgetattr(fd,&newtio);    
bzero(&newtio,sizeof(newtio));  
   //setting   c_cflag
newtio.c_cflag   &=~CSIZE;    
switch (databits) /*设置数据位数*/
{  
case 7:  
  newtio.c_cflag |= CS7; //7位数据位
  break;
case 8:    
  newtio.c_cflag |= CS8; //8位数据位
  break;  
default:  
  newtio.c_cflag |= CS8;
  break;    
}
switch (parity) //设置校验
{  
case 'n':
case 'N':  
  newtio.c_cflag &= ~PARENB;   /* Clear parity enable */
  newtio.c_iflag &= ~INPCK;     /* Enable parity checking */
  break;
case 'o':  
case 'O':    
  newtio.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
  newtio.c_iflag |= INPCK;             /* Disnable parity checking */
  break;
case 'e':
case 'E':  
  newtio.c_cflag |= PARENB;     /* Enable parity */  
  newtio.c_cflag &= ~PARODD;   /* 转换为偶效验*/    
  newtio.c_iflag |= INPCK;       /* Disnable parity checking */
  break;
case 'S':
case 's':  /*as no parity*/  
     newtio.c_cflag &= ~PARENB;
  newtio.c_cflag &= ~CSTOPB;break;
default:  
  newtio.c_cflag &= ~PARENB;   /* Clear parity enable */
  newtio.c_iflag &= ~INPCK;     /* Enable parity checking */
  break;  
}
switch (stopbits)//设置停止位
{  
case 1:  
  newtio.c_cflag &= ~CSTOPB;  //1
  break;
case 2:  
  newtio.c_cflag |= CSTOPB;  //2
    break;
default:
  newtio.c_cflag &= ~CSTOPB;
  break;
}
newtio.c_cc[VTIME] = 0;  
newtio.c_cc[VMIN] = 0;
newtio.c_cflag   |=   (CLOCAL|CREAD);
newtio.c_oflag|=OPOST;
newtio.c_iflag   &=~(IXON|IXOFF|IXANY);                    
    cfsetispeed(&newtio,baudrate);  
    cfsetospeed(&newtio,baudrate);  
    tcflush(fd,   TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&newtio) != 0)  
{
  perror("SetupSerial 3");
  return -1;
}
return 0;
}
int readport(int fd,char *buf,int len,int maxwaittime)//读数据,参数为串口,BUF,长度,超时时间
{
int no="0";int rc;int rcnum="len";
struct timeval tv;
fd_set readfd;
tv.tv_sec=maxwaittime/1000;    //SECOND
tv.tv_usec=maxwaittime%1000*1000;  //USECOND
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
rc=select(fd+1,&readfd,NULL,NULL,&tv);
if(rc>0)
{
  while(len)
  {
   rc=read(fd,&buf[no],1);
   if(rc>0)
    no=no+1;
   len=len-1;  
  }
  if(no!=rcnum)
   return -1;      //如果收到的长度与期望长度不一样,返回-1
  return rcnum;      //收到长度与期望长度一样,返回长度
}
else
{
  return -1;
}
return -1;
}
int writeport(int fd,char *buf,int len)  //发送数据
{
write(fd,buf,len);
}
void clearport(int fd)      //如果出现数据与规约不符合,可以调用这个函数来刷新串口读写数据
{
tcflush(fd,TCIOFLUSH);
}
main()  
{  
int   fd,rc,i,ret;  
unsigned char rbuf[256];
unsigned char wbuf[256]="";
for(i=0;i<256;i++)
  wbuf[i]=i;
char *dev ="/dev/ttyS0";    //串口号 /dev/ttyS0  对应于串口1
    fd  =  openport(dev);     //打开串口
if(fd>0)
{
  ret=setport(fd,4800,8,1,'o');  //设置串口,波特率,数据位,停止位,校验
  if(ret<0)
  {
   printf("Can't Set Serial Port!\n");
   exit(0);
  }
}
else
{
  printf("Can't Open Serial Port!\n");
  exit(0);
}
while(1){
  rc=readport(fd,rbuf,5,500);   //读取5个字节,超时时间为500毫秒
  if(rc>0)
  {
   writeport(fd,wbuf,rc);
   printf("recv:%d\n",rc);
   for(i=0;i<rc;i++)
   printf("%02x ",rbuf[i]);
   printf("\n");
  }
  else
   printf("recv none\n");
}  
close(fd);  
}  
今天说下利用VB如何进行串口读写。

首先需要的是在VB中增加一个microsoft   comm   control   6.0的控件。步骤就是:工程->部件->点击microsoft   comm   control   6.0->确定。

先介绍一下必须熟悉几个属性:

CommPort 设置并返回通讯端口号。
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen 设置并返回通讯端口的状态。也可以打开和关闭端口。
Input 从接收缓冲区返回和删除字符。
Output 向传输缓冲区写一个字符串。

然后利用给大家一个读串口的小例程:

Private Sub Form_Load()
Mcom.CommPort = 1 '选择com1
Mcom.Settings = "115200,N,8,1" '设置波特率为115.2kpbs,没有奇偶校验,8位数据位,1位结束位
Mcom.InputLen = 0 '读取全部的输入缓冲区
If Mcom.PortOpen = False Then Mcom.PortOpen = True '端口打开
Mcom.RThreshold = 2
Mcom.SThreshold = 2
End Sub

Private Sub Mcom_OnComm() '所有的通讯事件都可以激发MSComm1控件的OnComm事件
Select Case Mcom.CommEvent
Case comEvReceive'此处的代码可以进行当串口的接受缓冲区里有RThreshold个字符的处理
    Text4 = Text4 & Mcom.Input
Case comEvSend'此处的代码可以进行当串口的发送缓冲区里有SThreshold个字符的处理
  
End Select
End Sub

Private Sub Form_Unload(Cancel As Integer)
If Mcom.PortOpen = True Then Mcom.PortOpen = False
End Sub

利用上面的小程序,我们就可以通过读到外设给串口发出的数据了。

如果要发数据到串口就更简单了:

Private Sub SendC_Click()
    Dim sendbuff as string
    sendbuff = Text3
    Mcom.Output = sendbuff
End Sub

这样就可以将Text3中的数据发送到串口了。这就是一个最简单的串口读写例程了,操作的过程就是:初始化串口(端口、波特率等)->打开端口->利用接收buff读上传数据+发送buff写下传数据->完毕后关闭串口。

因为我也是最近在学习这个串口的读写,还没有深入下去。希望这个小例程能够帮到那些想要学习串口读写的人。
   笔记本电脑没有COM口(现在的笔记本都是没有COM口的),以前用的电脑属于老款式的,自带COM口,不需要考虑连接问题,这下如何连接笔记本和PLC成了难题。

    正在发愁的时候想到以前曾经听说过有种USB转COM的工具,马上去电子市场询问,那里的老板给我介绍了一个,很简单的东西,一头带个USB借口,另一头是个COM口,价格也不贵,花35元搞定。拿回来就着急着用,按部就班,装驱动,连线,一切准备就绪后就开始通讯,问题出现了,通讯失败!换了其他的 COM口,都失败(WINC软件有1-4个COM口),该不会是买了个坏的吧?

    琢磨了一下,马上意识到电脑本身的串口问题,于是打开设备管理器查看COM口,问题果然在那里,这台电脑的COM1,COM3,COM4全部被占用,在安装USB转COM的工具时它默认了COM5口,所以导致通讯不了,通过‘高级’修改COM5为COM2,然后设置PLC软件端口为COM2,通讯成功!

    有这个工具后,我们现在的串口通讯线也可以连接没有串口的电脑,不需要重新购买通讯电缆了!一点经历,希望给新手点帮助!
PHP 5.2.6 (cli) (built: May  2 2008 18:02:07),扩展了一个:extension=php_dio.dll
可以通过:mode com1 来查询com1的情况!

exec() 這個 PHP 函式執行 mode 外部指令,用來設定 com port 相關資訊,以範例來說是設定傳輸速率=19200、資料位元=8、停止位元=1、同位檢查=無,這要視設備而定,設定正確才能做存取動作。
_____________________________________Server端_______________________________
<?php

// --------------------------------------------------------------------------

// File name   : RS232_Server.php

// Description : RS232演示上位机程序

// Requirement : PHP 5.1.4 (cli) (http://www.php.net)

//

// Copyright(C), HonestQiao, 2006, All Rights Reserved.

//

// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)

//

// 程序简介:

// 本程序与RS232_Client构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。

// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:

// 协议内容:

//             C->S 01 //请求通讯

//             S->C 02 //响应通讯

//             C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据

//             C->S 03 //结束通讯

// 说明:S表示上位机 C表示下位机

//       HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的

//   请求和响应,数据帧的结构。

//       演示过程为通讯的请求和响应,十次数据帧的发送, 通讯的结束

//       数据帧的结构为当前的序号,microtime(),随机字符串

//

//       欢迎探讨PHP在RS232串口通讯上的应用。

// --------------------------------------------------------------------------

set_time_limit(0);
exec('mode COM1: baud=9600  data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM1:', O_RDWR);
if(!$fd)
{
  die("Error when open COM1");
}
$ff = dio_stat($fd);print_r($ff);
echo "HQB232 SERVER is listenning on COM1\n";
/// read
$len = 2;
$t=0;while (($t++)<1000)
{
  $data = dio_read($fd, $len);
  if ($data) {
    if($data==chr(0).chr(1)){
      echo "S_RECV:01\n";
      echo "S_SEND:02\n";
      dio_write($fd,chr(0).chr(2));
      break;
    }
  }
}
/// read
$len = 2;
$t=0;while (($t++)<1000)
{
  $len = 2;
  $data = dio_read($fd, $len);
  if($data==chr(0).chr(3)){
    echo "S_RECV:03\n";
    break;
  }
  elseif ($data) {
    $len = intval($data);
    $data = dio_read($fd, $len);
    if($data){
      echo "S_RECV:($len)$data\n";
    }
  }
}
dio_close($fd);
?>





_____________________________________client端_______________________________


<?php

// --------------------------------------------------------------------------

// File name   : RS232_Client.php

// Description : RS232演示下位机程序

// Requirement : PHP 5.1.4 (cli) (http://www.php.net)

//

// Copyright(C), HonestQiao, 2006, All Rights Reserved.

//

// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680)

//

// 程序简介:

// 本程序与RS232_Server构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。

// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:

// 协议内容:

//             C->S 01 //请求通讯

//             S->C 02 //响应通讯

//             C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据

//             C->S 03 //结束通讯

// 说明:S表示上位机 C表示下位机

//       HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的

//   请求和响应,数据帧的结构。

//       演示过程为通讯的请求和响应,十次数据帧的发送, 通讯的结束

//       数据帧的结构为当前的序号,microtime(),随机字符串

//

//       欢迎探讨PHP在RS232串口通讯上的应用。

// --------------------------------------------------------------------------

set_time_limit(0);
//exec('mode COM1: baud=9600 data=8 stop=1 parity=n xon=on');
exec('mode COM1: baud=9600  data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM1:', O_RDWR);
if(!$fd)
{
  die("Error when open COM1");
}
$ff = dio_stat($fd);
echo "HQB232 CLIENT is start on COM1\n";
dio_write($fd,chr(0).chr(1));echo "C_SEND:01\n";
$len = 2;
$t=0;while(($t++)<1000)
{
  $data = dio_read($fd, $len);
  if($data==chr(0).chr(2)){
    echo "C_RECV:02\n";
    break;
  }
}
$len = 2;
$t=0;while(($t++)<10)
{
  $sdata = sprintf("%03d",$t) . "=" . microtime() . " (" . randomkeys(rand(0,35)) . ")";
  $slen = strlen($sdata);
  $stxlen = sprintf("%02d",$slen);
  dio_write($fd,"$stxlen");
  dio_write($fd,"$sdata");
    echo "C_SEND:($stxlen)$sdata\n";
  //sleep(1);
}
dio_write($fd,chr(0).chr(3));echo "C_SEND:03\n";
dio_close($fd);
function randomkeys($length)
{
   $pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
   for($i=0;$i<$length;$i++)
   {
     $key .= $pattern{rand(0,35)};
   }
   return $key;
}
?>


注意:在window下com是当作一个文件打开的,只能有一个进程控制,可能导致clien 或者 server 出现:Warning: dio_open(): cannot open file COM1: with flags 2 and permissions 0: Permission denied in ****
分页: 235/272 第一页 上页 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 下页 最后页 [ 显示模式: 摘要 | 列表 ]