??xml version="1.0" encoding="utf-8" standalone="yes"?> 1?/span>diff Q-Q-Q-Q-Q-Q-Q-Q-Q-Q- NAME diff - find differences between two files SYNOPSIS diff [options] from-file to-file Q-Q-Q-Q-Q-Q-Q-Q-Q-Q- 单的_diff的功能就是用来比较两个文件的不同Q然后记录下来,也就是所谓的diff补丁。语法格式:diff 【选项?/span> 源文Ӟ夹) 目的文gQ夹Q?/span>Q就是要l?span style="COLOR: green">源文Ӟ夹)打个补丁Q之变?span style="COLOR: fuchsia">目的文gQ夹Q?/span>Q术语也是“升”。下面介l三个最为常用选项Q?/span> -r 是一个递归选项Q设|了q个选项Q?/span>diff会将两个不同版本源代码目录中的所有对应文件全部都q行一ơ比较,包括子目录文件?/span> -N 选项保补丁文g正地处理已经创徏或删除文件的情况?/span> -u 选项以统一格式创徏补丁文gQ这U格式比~省格式更紧凑些?/span> 2?/span>patch Q-Q-Q-Q-Q-Q-Q-Q-Q- NAME patch - apply a diff file to an original SYNOPSIS patch [options] [originalfile [patchfile]] but usually just patch -pnum <patchfile> Q-Q-Q-Q-Q-Q-Q-Q-Q- 单的_patch是利用diff制作的补丁来实现源文Ӟ夹)?span style="COLOR: fuchsia">目的文gQ夹Q?/span>的{换。这栯意味着你可以有源文Ӟ夹)―?/span>>目的文gQ夹Q?/span>Q也可以目的文gQ夹Q?/span>―?/span>>源文Ӟ夹)?/span>下面介绍几个最常用选项Q?/span> -p0 选项要从当前目录查找目的文gQ夹Q?/span> -p1 选项要忽略掉W一层目录,从当前目录开始查找?/span> ************************************************************ 在这里以实例说明Q?/span> --- old/modules/pcitable Mon Sep 27 11:03:56 1999 +++ new/modules/pcitable Tue Dec 19 20:05:41 2000 如果使用参数-p0Q那pCZ当前目录找一个叫做old的文件夹Q在它下面寻找modules下的pcitable文g来执行patch操作?/font> 如果使用参数-p1Q那pC忽略第一层目录(即不oldQ,从当前目录寻找modules的文件夹Q在它下面找pcitable。这L前提是当前目 录必Mؓmodules所在的目录。而diff补丁文g则可以在L位置Q只要指明了diff补丁文g的\径就可以了。当Ӟ可以用相对\径,也可以用l?对\径。不q我一般习惯用相对路径?/font> -E 选项说明如果发现了空文gQ那么就删除?/span> -R 选项说明在补丁文件中?/span>“?/span>”文g?/span>“?/span>”文g现在要调换过来了Q实际上是l新版本打补丁,让它变成老版本) 下面l合具体实例来分析和解决Q分ZU类型:为单个文件打补丁和ؓ文g夹内的多个文件打补丁?/span> 环境Q在RedHat 9.0下面?/span>armlinux用户登陆?/span> 目录树如下: |-- bootloader |-- debug |-- images |-- kernel |-- program |-- rootfiles |-- software |-- source |-- sysapps |-- tmp `-- tools 下面?/span>program文g夹下面徏?/span>patch文g夹作为实验用Q然后进?/span>patch文g夏V?/span> 一、ؓ单个文gq行补丁操作 1、徏立测试文?/span>test0?/span>test1 [armlinux@lqm patch]$ cat >>test0<<EOF > 111111 > 111111 > 111111 > EOF [armlinux@lqm patch]$ more test0 111111 111111 111111 [armlinux@lqm patch]$ cat >>test1<<EOF > 222222 > 111111 > 222222 > 111111 > EOF [armlinux@lqm patch]$ more test1 222222 111111 222222 111111 2、?/span>diff创徏补丁test1.patch [armlinux@lqm patch]$ diff -uN test0 test1 > test1.patch 【注Q因为单个文Ӟ所以不需?/span>-r选项。选项序没有关系Q即可以?/span>-uNQ也可以?/span>-Nu。?/span> [armlinux@lqm patch]$ ls test0 test1 test1.patch [armlinux@lqm patch]$ more test1.patch ************************************************************ patch文g的结?/span> 补丁?/span> 补丁头是分别?/span>---/+++开头的两行Q用来表C打补丁的文g?/span>---开头表C旧文gQ?/span>+++开头表C新文g?/span> 一个补丁文件中的多个补?/span> 一个补丁文件中可能包含?/span>---/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁?/span> ?/span> 块是补丁中要修改的地斏V它通常׃部分不用修改的东西开始和l束。他们只是用来表C修改的位|。他们通常?/span>@@开始,l束于另一个块的开始或者一个新的补丁头?/span> 块的~进 块会~进一列,而这一列是用来表示q一行是要增加还是要删除的?/span> 块的W一?/span> +可C一行是要加上的?/span> -可C一行是要删除的?/span> 没有加号也没有减可C里只是引用的而不需要修攏V?/span> ************************************************************ ***diff命o会在补丁文g中记录这两个文g的首ơ创建时_如下*** --- test0 2006-08-18 09:12:01.000000000 +0800 +++ test1 2006-08-18 09:13:09.000000000 +0800 @@ -1,3 +1,4 @@ +222222 111111 -111111 +222222 111111 [armlinux@lqm patch]$ patch -p0 < test1.patch patching file test0 [armlinux@lqm patch]$ ls test0 test1 test1.patch [armlinux@lqm patch]$ cat test0 222222 111111 222222 111111 3、可以去除补丁,恢复旧版?/span> [armlinux@lqm patch]$ patch -RE -p0 < test1.patch patching file test0 [armlinux@lqm patch]$ ls test0 test1 test1.patch [armlinux@lqm patch]$ cat test0 111111 111111 111111 二、ؓ多个文gq行补丁操作 1、创建测试文件夹 [armlinux@lqm patch]$ mkdir prj0 [armlinux@lqm patch]$ cp test0 prj0 [armlinux@lqm patch]$ ls prj0 test0 test1 test1.patch [armlinux@lqm patch]$ cd prj0/ [armlinux@lqm prj0]$ ls test0 [armlinux@lqm prj0]$ cat >>prj0name<<EOF > -------- > prj0/prj0name > -------- > EOF [armlinux@lqm prj0]$ ls prj0name test0 [armlinux@lqm prj0]$ cat prj0name -------- prj0/prj0name -------- [armlinux@lqm prj0]$ cd .. [armlinux@lqm patch]$ mkdir prj1 [armlinux@lqm patch]$ cp test1 prj1 [armlinux@lqm patch]$ cd prj1 [armlinux@lqm prj1]$ cat >>prj1name<<EOF > --------- > prj1/prj1name > --------- > EOF [armlinux@lqm prj1]$ cat prj1name --------- prj1/prj1name --------- [armlinux@lqm prj1]$ cd .. 2、创?/span> [armlinux@lqm patch]$ diff -uNr prj0 prj1 > prj1.patch [armlinux@lqm patch]$ more prj1.patch diff -uNr prj0/prj0name prj1/prj0name --- prj0/prj0name 2006-08-18 09:25:11.000000000 +0800 +++ prj1/prj0name 1970-01-01 08:00:00.000000000 +0800 @@ -1,3 +0,0 @@ --------- -prj0/prj0name --------- diff -uNr prj0/prj1name prj1/prj1name --- prj0/prj1name 1970-01-01 08:00:00.000000000 +0800 +++ prj1/prj1name 2006-08-18 09:26:36.000000000 +0800 @@ -0,0 +1,3 @@ +--------- +prj1/prj1name +--------- diff -uNr prj0/test0 prj1/test0 --- prj0/test0 2006-08-18 09:23:53.000000000 +0800 +++ prj1/test0 1970-01-01 08:00:00.000000000 +0800 @@ -1,3 +0,0 @@ -111111 -111111 -111111 diff -uNr prj0/test1 prj1/test1 --- prj0/test1 1970-01-01 08:00:00.000000000 +0800 +++ prj1/test1 2006-08-18 09:26:00.000000000 +0800 @@ -0,0 +1,4 @@ +222222 +111111 +222222 +111111 [armlinux@lqm patch]$ ls prj0 prj1 prj1.patch test0 test1 test1.patch [armlinux@lqm patch]$ cp prj1.patch ./prj0 [armlinux@lqm patch]$ cd prj0 [armlinux@lqm prj0]$ patch -p1 < prj1.patch patching file prj0name patching file prj1name patching file test0 patching file test1 [armlinux@lqm prj0]$ ls prj1name prj1.patch test1 [armlinux@lqm prj0]$ patch -R -p1 < prj1.patch patching file prj0name patching file prj1name patching file test0 patching file test1 [armlinux@lqm prj0]$ ls prj0name prj1.patch test0 Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?/span> ȝ一下: 单个文g diff –uN from-file to-file >to-file.patch patch –p0 < to-file.patch patch –RE –p0 < to-file.patch 多个文g diff –uNr from-docu to-docu >to-docu.patch patch –p1 < to-docu.patch patch –R –p1 <to-docu.patch
]]>
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
2. 如果要已l处于连接状态的soket在调用closesocket后强制关闭,不经?br>TIME_WAIT的过E:
BOOL bDontLinger = FALSE;
setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));
3.在send(),recv()q程中有时由于网l状늭原因Q发收不能预期进?而设|收发时限:
int nNetTimeout=1000;//1U?br>//发送时?br>setsockopt(socketQSOL_S0CKET,SO_SNDTIMEOQ?char *)&nNetTimeout,sizeof(int));
//接收旉
setsockopt(socketQSOL_S0CKET,SO_RCVTIMEOQ?char *)&nNetTimeout,sizeof(int));
4.在send()的时候,q回的是实际发送出ȝ字节(同步)或发送到socket~冲区的字节
(异步);pȝ默认的状态发送和接收一ơؓ8688字节(Uؓ8.5K)Q在实际的过E中发送数?br>和接收数据量比较大,可以讄socket~冲区,而避免了send(),recv()不断的@环收发:
// 接收~冲?br>int nRecvBuf=32*1024;//讄?2K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
//发送缓冲区
int nSendBuf=32*1024;//讄?2K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));
5. 如果在发送数据的Ӟ希望不经历由pȝ~冲区到socket~冲区的拯而媄?br>E序的性能Q?br>int nZero=0;
setsockopt(socketQSOL_S0CKET,SO_SNDBUFQ?char *)&nZero,sizeof(nZero));
6.同上在recv()完成上述功能(默认情况是将socket~冲区的内容拯到系l缓冲区)Q?br>int nZero=0;
setsockopt(socketQSOL_S0CKET,SO_RCVBUFQ?char *)&nZero,sizeof(int));
7.一般在发送UDP数据报的时候,希望该socket发送的数据hq播Ҏ:
BOOL bBroadcast=TRUE;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));
8.在clientq接服务器过E中Q如果处于非d模式下的socket在connect()的过E中?br>以设|connect()延时,直到accpet()被呼?本函数设|只有在非阻塞的q程中有显著?br>作用Q在d的函数调用中作用不大)
BOOL bConditionalAccept=TRUE;
setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));
9.如果在发送数据的q程?send()没有完成Q还有数据没发?而调用了closesocket(),以前我们
一般采取的措施?从容关闭"shutdown(s,SD_BOTH),但是数据是肯定丢׃Q如何设|让E序满具体
应用的要?卌没发完的数据发送出d在关闭socket)Q?br>struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff=1;//(在closesocket()调用,但是q有数据没发送完毕的时候容讔R留)
// 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;
m_sLinger.l_linger=5;//(容许逗留的时间ؓ5U?
setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
讄套接口的选项?br>
#include <winsock.h>
int PASCAL FAR setsockopt( SOCKET s, int level, int optname,
const char FAR* optval, int optlen);
sQ标识一个套接口的描q字?br> levelQ选项定义的层ơ;目前仅支持SOL_SOCKET和IPPROTO_TCP层次?br> optnameQ需讄的选项?br> optvalQ指针,指向存放选项值的~冲区?br> optlenQoptval~冲区的长度?br>
注释Q?br> setsockopt()函数用于Lcd、Q意状态套接口的设|选项倹{尽在不同协议层上存在选项Q但本函C定义了最高的“套接?#8221;层次上的选项。选项影响套接口的操作Q诸如加急数据是否在普通数据流中接Ӟq播数据是否可以从套接口发送等{?br> 有两U套接口的选项Q一U是布尔型选项Q允许或止一U特性;另一U是整Ş或结构选项。允怸个布型选项Q则optval指向非零整Ş敎ͼ止一个选项optval指向一个等于零的整形数。对于布型选项Qoptlen应等于sizeof(int)Q对其他选项Qoptval指向包含所需选项的整形数或结构,而optlen则ؓ整Ş数或l构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,且closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的媄响。应用程序通过创徏一个lingerl构来设|相应的操作Ҏ:
struct linger {
int l_onoff;
int l_linger;
};
Z允许SO_LINGERQ应用程序应l_onoff设ؓ非零Q将l_linger设ؓ零或需要的时|以秒为单位)Q然后调?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">setsockopt()。ؓ了允许SO_DONTLINGERQ亦即禁止SO_LINGERQ,l_onoff应设为零Q然后调?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">setsockopt()?br> ~省条g下,一个套接口不能与一个已在用中的本地地址捆绑Q参见bind()Q。但有时会需?#8220;重用”地址。因为每一个连接都由本地地址和远端地址的组合唯一定Q所以只要远端地址不同Q两个套接口与一个地址捆绑q无大碍。ؓ了通知WINDOWS套接口实C要因Z个地址已被一个套接口使用׃让它与另一个套接口捆绑Q应用程序可在bind()调用前先讄SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释Q故此无需Q但也无宻I一个不会共用地址的套接口讄该选项Q或者在bind()对这个或其他套接口无影响情况下设|或清除q一选项?br> 一个应用程序可以通过打开SO_KEEPALIVE选项Q得WINDOWS套接口实现在TCPq接情况下允怋?#8220;保持zd”包。一个WINDOWS套接口实现ƈ不是必需支持“保持zd”Q但是如果支持的话,具体的语义将与实现有养I应遵守RFC1122“InternetL要求Q通讯?#8221;中第4.2.3.6节的规范。如果有兌接由?#8220;保持zd”而失效,则进行中的Q何对该套接口的调用都以WSAENETRESET错误q回Q后l的M调用以WSAENOTCONN错误q回?br> TCP_NODELAY选项止Nagle法。Nagle法通过未认的数据存入缓冲区直到蓄一个包一起发送的ҎQ来减少L发送的零碎数据包的数目。但对于某些应用来说Q这U算法将降低pȝ性能。所以TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在切了解它的效果q确实需要的情况下,才设|TCP_NODELAY选项Q因|后对网l性能有明昄负面影响。TCP_NODELAY是唯一使用IPPROTO_TCP层的选项Q其他所有选项都用SOL_SOCKET层?br> 如果讄了SO_DEBUG选项QWINDOWS套接口供应商被鼓励(但不是必需Q提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨围?br> setsockopt()支持下列选项。其?#8220;cd”表明optval所指数据的cd?br>选项 cd 意义
SO_BROADCAST BOOL 允许套接口传送广播信息?br>SO_DEBUG BOOL 记录调试信息?br>SO_DONTLINER BOOL 不要因ؓ数据未发送就d关闭操作。设|本选项相当于将SO_LINGER的l_onoff元素|ؓ零?br>SO_DONTROUTE BOOL 止选径Q直接传送?br>SO_KEEPALIVE BOOL 发?#8220;保持zd”包?br>SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留?br>SO_OOBINLINE BOOL 在常规数据流中接收带外数据?br>SO_RCVBUF int 为接收确定缓冲区大小?br>SO_REUSEADDR BOOL 允许套接口和一个已在用中的地址捆绑Q参见bind()Q?br>SO_SNDBUF int 指定发送缓冲区大小?br>TCP_NODELAY BOOL 止发送合q的Nagle法?br>
setsockopt()不支持的BSD选项有:
选项? cd 意义
SO_ACCEPTCONN BOOL 套接口在监听?br>SO_ERROR int 获取错误状态ƈ清除?br>SO_RCVLOWAT int 接收低水印?br>SO_RCVTIMEO int 接收时?br>SO_SNDLOWAT int 发送低U水印?br>SO_SNDTIMEO int 发送超时?br>SO_TYPE int 套接口类型?br>IP_OPTIONS 在IP头中讄选项?br>
q回|
若无错误发生Q?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">setsockopt()q回0。否则的话,q回SOCKET_ERROR错误Q应用程序可通过WSAGetLastError()获取相应错误代码?br>
错误代码Q?br> WSANOTINITIALISEDQ在使用此API之前应首先成功地调用WSAStartup()?br> WSAENETDOWNQWINDOWS套接口实现检到|络子系l失效?br> WSAEFAULTQoptval不是q程地址I间中的一个有效部分?br> WSAEINPROGRESSQ一个阻塞的WINDOWS套接口调用正在运行中?br> WSAEINVALQlevel值非法,或optval中的信息非法?br> WSAENETRESETQ当SO_KEEPALIVE讄后连接超时?br> WSAENOPROTOOPTQ未知或不支持选项。其中,SOCK_STREAMcd的套接口不支持SO_BROADCAST选项QSOCK_DGRAMcd的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项?br> WSAENOTCONNQ当讄SO_KEEPALIVE后连接被复位?br> WSAENOTSOCKQ描q字不是一个套接口?br>
参见Q?br> bind(), getsockopt(), ioctlsocket(), socket(), WSAAsyncSelect().
copy from:http://blog.csdn.net/qinmi/archive/2007/03/07/1523081.aspx
一?UPnP是用来干什么的Q?/p>
|络发展到现在,已经可以使我们在|上冲浪、收发邮件、听到远方传送来的声韟뀁搜索感兴趣的内宏V下载Y件、点播节目、即时聊?#8230;…实现的功能好像已l不,但,人的Ʋ望无止境,享福x享福Q还有许多目标没有达刎ͼ例如Q怎样才能使我们在|络上,像^时用遥控器那P操作I器、电风扇、厨房电器,或网l远端的电器讑֤呢?如何利用|络上的计算源,使这U?#8220;遥控”更具化?甚至Q将一pd相关的控制写C个脚本中Q以便用户定制自己所喜爱的控制流E?#8230;…实现诸如此类的效果,是有巨大需求的应用技术。如果实现通过|络用UPnP控制家用讑֤Q将l我们的生活带来很大的方便和很多新的体验。例如:
1.你在下班之前Q或在回ȝ路上Q就可以先打开安的空调器和厨房设备,{进入家门,立刻是一个温度宜人的环境――厨戉K的饭也做好了。房间温度的高低和厨房内煮饭的过E,都是Ҏ事先设计好的“脚本”E序q行的,l对可靠?/p>
2.你若是一位上档次的音乐发烧者,肯定对聆听音乐的环境要求很严Q音׃|高低、音量大、灯光明暗、窗帘拉不拉上都有讲I。手动控刉好,毕竟不方ѝ你要用上UPnPQ一切都会ؓ你代功뀂还能将你习惯的韛_音量、灯光亮度、音q高度{等Q以你认为最佳的参数写到执行脚本中,以后可以都以此ؓ准。如果你拥有自己的专门听韛_Q只要你打开听音室的门,上述的环境就会立刻设|好。曲lh散,只管攑ֿd好了QUPnPpȝ会自己关闭音响,熄灭늁Q拉上窗帘?/p>
3.你h在办公室Q心里却放不下家里的孩子。用上UPnPQ只要在安安装摄像_建立好与|络的连接。在办公室内Q启用桌面电脑的WEBTVQ连通网l后Q可以即时监视孩子在安的一举一动?/p>
凡此U种的方便和׃h之处q很多,不胜枚D?/p>
其实Q这已经不是U学qL、也不是专家预言。目前用UPnP协议可以实现这些操作!q正是windows xppȝ急于加入UPnP的原因。正因ؓUPnP是一个协议,UPnP的用可跨越各种操作pȝq_Q开发应用程序也没有开发语a的局限。可工作于各UŞ式的|络l构。且仅以现在的网l设施ؓ基础Q仅仅加上这个UPnP协议Q既不用d新的设施Q也不用重新架设|络介质可以投入用!
UPnP协议h下述特色Q?/p>
1. 以网lؓ应用环境Q不考虑“孤岛”中的计算机?/p>
2. 以TCP/IP和整个Internet为基。这h“中立”的,不依附于M操作pȝ或应用程序,不用特定的API函数Q不受程序设计语a的局限。可以无~地接入传统|络?/p>
3. 讑֤可以动态地q入|络中,随后获得IP地址Q?#8220;学习” 或查找自己应当进行的操作和服务的信息Q?#8220;感知”别的讑֤是否存在以及它们的作用和当前的状?。所有这些,都应当是可自动完成的?/p>
4. 每个讑֤都可d属于自己的、特定的状态和参数Q完成控制操作后应当发出“操作完成”的响应信受如果失败,则应发出控制p|的信受?/p>
二、UPnP协议的层Q?/p>
UPnP协议的最l目的,是徏立一个可用的讑֤模型Q?因篇q这里不Ҏ个结构进行详l的分析Q但你应当记住下面的主要特征Q?/p>
1. UPnP是一个多层协议构成的框架体系Q每一层都以相ȝ下层为基Q同时又是相M层的基础。直臌到应用层为止。该图中的最下面是就是IP和TCPQ共两层Q负责设备的IP地址?/p>
2. 三层是HTTP、HTTPU、HTTPMUQ这一层,大家应当是熟悉的Q属于传送协议层。传送的是内定wl过“装”后,存放在特定的XML文g中的。对应的SSDP、GENA、SOAP指的是保存在XML文g中的数据格式。到q一层,已经解决了UPnP讑֤的IP地址和传送信息问题?/p>
3. W四层是UPnP讑֤体系定义Q仅仅是一个抽象的、公用的讑֤模型。Q何UPnP讑֤都必M用这一层?/p>
4. W五层是UPnP论坛的各个专业委员会的设备定义层Q在q个论坛中,不同电器讑֤׃同的专业委员会定义,例如Q电视委员会只负责定义网l电视设备部分,I器委员会只负责定义网l空调设备部?#8230;…依此cL。所有的不同cd的设备都被定义成一个专门的架构或者模板,供徏立设备的时候用。可以推知,q入q一层,讑֤已经被指定了明确用途。当Ӟq些都必遵守标准化的规范。从目前看,UPnP已经可以支持大部分的讑֤Q从电脑、电脑外设,Ud讑֤和家用消费类电子讑֤{等Q无所不包Q随着q个体系的普及,可能有更多的厂家承认这一标准Q最l,可能演化为公认的行业标准?/p>
5. 最上层Q也是应用层,由UPnP讑֤刉厂商定义的部分。这一层的信息是由讑֤刉厂商来“填充” 的,q部分一般有讑֤厂商提供的、对讑֤控制和操作的底层代码Q然后,是名称序列号呀Q厂商信息之cȝ东西?/p>
三、协议内部的详细情况
仅仅有这样五层UPnP协议Q也只不q有了一个共同遵守的框架Q实际的UPnPpȝI竟是如何构成的呢?
完整的UPnP服务pȝ由支持UPnP的网l和W合UPnP规范的设备共同构成的?/p>
整个pȝ是由讑֤、服务、和控制指针三部分所构成?/p>
讑֤Q?/p>
q里是指W合UPnP规范的设备。一个UPnP讑֤可以看成一个包含服务ƈ嵌套了常规设备的“容器” 。例如,一个UPnP的VCRQ录像机Q设备可以包含磁带传送服务、调谐服务和旉服务。就是说QUPnP之下的设备不能仅仅理解ؓg意义上的讑֤Q而应当包括服务功能?/p>
不同U类的UPnP讑֤关联不同的讄、服务和嵌入讑֤。如打印机和VCR属于不同用途的讑֤Q服务就不可能定义成一L?/p>
服务Q?/p>
讑֤执行用户h的控制过E,可划分成一个个很小的阶D|单位Q每个单位就UCؓ一个服务。每一个服务,对外都表Cؓ具体的行为和模式Q而行为和模式又可以用状态和变量D行描q。只要可以用数值描qͼ在计机里面容易处理了。例如,模仿一个时钟,它只有一个工作模式:q个模式是模拟q显C当前的旉。而一个时钟的行ؓ共有两种Q也只有两种Q:
1. 讄旉Q用?#8220;卛_^时说的对?#8221;Q?
2. 得到旉Q用于显C时_?/p>
其它讑֤服务Q也是用q样思\来描q和定义的,一个设备也可以被定义多个服务。不论是讑֤的定义信息和服务的描qC息,都保存在一个XML文g中,q个文g也是UPnP协议构成的一部分。当讑֤建立和用服务的时候,XML文g可以与它们进行关联?/p>
XML文g中还有一个很关键?#8220;状态表”Q状态表可进一步分?#8220;服务状态表”?#8220;事g状态表”。整个UPnP讑֤q行的全q程内,状态表贯穿始终Q当讑֤状态改变的时候,例如发生参数变化或状态刷新的时候,立即在“状态表”中反映出来。如控制服务器在接收到设|时间的行ؓhӞqx行请求(Ҏ操作Q,q给出响应,同时更新状态表中的有关数据。相应地Q事件服务器负责向对此事件感兴趣的设备公布所发生的状态改变。例如,一个火灾事件发生后Q事件服务器向火灾报警器发布这个事ӞD报警器动作生报警信受?/p>
控制指针Q?/p>
在UPnP|络中,用户h讑֤执行的控制是通过控制指针实现的,控制指针首先是一个有能力控制别的讑֤的控制者,q要h在网l中 “发现”控制目标的能力。在发现Q控制目标)之后Q控制指针应当:
①取得设备的描述信息q得到所兌的服务列表?/p>
②取得相x务的描述?/p>
③调用控制服务行为?/p>
④确定服务的事g “?#8221;Q不ZӞ只要服务状态发生改变,事g服务器会立即向控制指针发送一个事件信息?/p>
从上面说到的各种信息Q都保存在XML文g中,不同用途的信息Q格式不同。保证可以各取所需Q不会淆?/p>
那么QUPnP的完整工作过E是怎样的呢Q?/p>
UPnP在控制指针和被控制设备之间提供通讯功能。而网l介质、TCP/IP协议、HTTP仅提供基本的q接和IP地址分配。整个工作过E需要处理六个方面的内容Q即地址分配、发现设备、对讑֤的描q、设备控制、设备事件、设备表达?/p>
地址问题Q?/p>
地址是整个UPnPpȝ工作的基条gQ每个设备都应当是DHCPQDynamic Host Configuration Protocol 动态主机配|协议)的客戗当讑֤首次与网l徏立连接后Q利用DHCP服务Q讑֤得到一个IP地址。这个IP地址可以是DHCPpȝ指定的,也可以是p备选择的,当然Q有能力自己选择IP地址的设备,必然是那?#8220;聪明”的设备才行!q也是所谓的“自动”IP地址?/p>
如果遇到本地DHCP理范围之外的IP地址hQ还需要解?#8220;友好讑֤”
的地址分配问题Q这个问题通常由域名服务器来解冟?/p>
发现讑֤Q?/p>
可分成两U情况,一U是在有控制h之后Q在当前的网l中查找有无对应的可用设备;另一U情冉|某一讑֤接入|络、取得IP地址之后Q就开始向|络“q播”自己已经q入|络Q即L控制h?/p>
讑֤的描qͼ
单说Q这是声?#8220;自己”是什么样的设备,例如名称、制造厂商、序列号码等{。刚开?#8220;发现”讑֤后,控制指针对这个设备的“了解”q很,需要依据ULR扑ֈ该设备的描述文gQ从q些文g中读取更多的描述信息。描qC息的范围很广Q一般都是由讑֤的制造厂商提供的。主要的描述目有:控制的模式名U和模式L、设备序列号、制造厂商名U、厂商的WEB的ULR{等。这些一般都存放在特定的XML文g中;
讑֤控制Q?/p>
控制指针扑ֈ讑֤描述之后Q会从描qC“提炼”q行的操作ƈh所有的服务Q对每个UPnP讑֤来说Q这些描q必L很确切、很详细的,描述中可能包含有命o或行为列表、服务响应信息、用到的参数{等。对于服务的每个行ؓQ也伴有描述信息Q主要是整个服务q行期间的变量、变量的数据cd、可用的取D围和事g的特征?/p>
要控制某个设备,控制指针必须先发送一个控制行求,要求讑֤开始服务,然后再按讑֤的ULR发送相应的控制消息Q控制消息就是放|在XML文g中的那些SOAP格式的信息。最后,服务会返回响应信息,指出服务是成功或是失败?/p>
讑֤事gQ?/p>
在服务进行的整个旉内,只要变量值发生了变化或者模式的状态发生了改变Q就产生了一个事Ӟpȝ修改上q提到的事g列表的内宏V随之,事g服务器把事g向整个网l进行广播。另一斚wQ控制指针也可以事先向事件服务器预约事g信息Q保证将该控制指针感兴趣的事件及时准地传送过来?/p>
q播或预U事Ӟ传送的都是事g消息Q事件消息也攑֜XML文g中,使用的格式是GENA?/p>
讑֤投入工作之前的准备―――初始化q程Q也是一个事Ӟ初始化需要的各种信息也是用事件消息传送的。包括的内容主要是:变量初始|模式的初始状态等{?/p>
讑֤表达Q?/p>
只要得到了设备的ULRQ就可以取得该设备表N面的ULRQ然后可以将此表辄入用L本地览器上。这部分q包括与用户对话的界面,以及与用戯行会话的处理?/p>
整个UPnPpȝQ是?#8220;中枢经”的指挥下协同工作的。其大致情Ş如下Q?/p>
凡是具备IP地址的的讑֤都必ȝ接用网l的IP地址Q但有些讑֤可能q不具备直接使用|络IP地址的能力,例如Q电灯开关的控制是q样Q这是非IP讑֤Q非IP讑֤通过|桥QUPnP BridgeQ来与控制指针交换信息?/p>
直接使用IP地址的有Q控制指针(可在口袋电脑和远E设备上发出控制Q、本地设备,例如VCR和时钟;以及|桥。非IP讑֤有所谓轻讑֤Q如温度控制器)和非UPnP的设备(如电灯控制开关等Q?/p>
上述介绍属于g斚wQ下面再说作为控制灵的软gQ?/p>
在上面的叙述中,多次提到用XML文g存放需要的信息Q因为无论是控制指针或设备服务,都需要很多信息,有读出的Q有传出的,UPnP协议U定q些都存攑֜特定的文件XML中。用途不同的信息Q在XML文g中的格式不同。所以,相关的XML文g是控制服务的灵魂?/p>
四、关于UPnP隐藏的安全缺~陷Q?/p>
q次发现的安全缺陷共有两个,其中W一个缺h对缓冲区QBufferQ的使用没有q行查和限制。外部的d者,可以通过q里取得整个pȝ的控制特权!׃UPnp功能必须使用计算机的端口来进行工作,取得控制权的d者,q有可能利用q些端口Q达到攻击者的目的。这个缺陷导致的后果很严重,不论那个版本的windows pȝQ只要运行UPnPQ就都存在这个危险!但严格地_qƈ不完全是UPnP技术本w的问题Q更多的是程序设计的疏忽?/p>
W二个缺陷就与UPnP的工作机理有关系了!
该缺陷存在于UPnP工作时的“讑֤发现”阶段。发现设备可以分ZU情况:如果某个具备UPnP功能的计机引导成功q连接到|络上,׃立刻向网l发?#8220;q播”Q向|络上的UPnP讑֤通知自己已经准备qAQ在E序设计q一U别上看Q该q播内容是一个M-SEARCHQ消息)指示。该q播被“声音所?#8221;范围之内的所有设备所“听到”。ƈ向该计算机反馈自q有关信息Q以备随后进行控制之用?/p>
相类|如果某个讑֤刚刚q接到网l上Q也会向|络发出“通知”Q表C己准备就l,可以接受来自|络的控Ӟ在程序设计这一U别上看Q该通知是一个NOTIFYQ消息)指示。也被“声音所?#8221;范围之内的所有计机接受。计机?“感知”该设备已l向自己“报到”。实际上QNOTIFYQ消息)指示也不是单单发送给计算机听的,别的|络讑֤也可以听到?/p>
是在上q的一播一听之_出现了问题!
如果某个黑客向某个用Ll发送一个NOTIFYQ消息)指示Q该用户pȝ׃收到q个NOTIFYQ消息)指示q在其指CZQ连接到一个特定服务器上,接着向相应的服务器请求下载服务―――下载将要执行的服务内容。服务器当然会响应这个请求。UPnP服务pȝ解释这个设备的描述部分Q请求发送更多的文gQ服务器又需要响应这些请求。这P构成一?#8220;h――响?#8221;的@环,大量占用pȝ资源Q造成UPnPpȝ服务速度变慢甚至停止。所以,q个~陷导?#8220;拒绝服务”dUCؓ可能Q?/p>
l束?/p>
UpnP正在向我们一步步走近Q现在已l是_可闻了。不久的来Q必然对我们的工作和生活产生巨大影响。也蕴含着无限商机。尽现在存在问题,也难保以后就不会再出现新的问题,但这既然体现了h的需求意向,׃有巨大的生命力,暂时的挫折不会得它停下前进的脚步!
Visual Studio 2003/Visual Studio 2005常用快捷?快捷方式)
调试快捷?/p>
F6: 生成解决Ҏ
Ctrl+F6: 生成当前目
F7: 查看代码
Shift+F7: 查看H体设计?br />F5: 启动调试
Ctrl+F5: 开始执?不调?
Shift+F5: 停止调试
Ctrl+Shift+F5: 重启调试
F9: 切换断点
Ctrl+F9: 启用/停止断点
Ctrl+Shift+F9: 删除全部断点
F10: 逐过E?br />Ctrl+F10: q行到光标处
F11: 逐语?/p>
~辑快捷?/p>
Shift+Alt+Enter: 切换全屏~辑
Ctrl+B,T / Ctrl+K,K: 切换书签开?br />Ctrl+B,N / Ctrl+K,N: UdC一书签
Ctrl+B,P: UdC一书签
Ctrl+B,C: 清除全部标签
Ctrl+I: 渐进式搜?br />Ctrl+Shift+I: 反向渐进式搜?br />Ctrl+F: 查找
Ctrl+Shift+F: 在文件中查找
F3: 查找下一?br />Shift+F3: 查找上一?br />Ctrl+H: 替换
Ctrl+Shift+H: 在文件中替换
Alt+F12: 查找W号(列出所有查扄?
Ctrl+Shift+V: 剪脓板@?/p>
Ctrl+左右头? 一ơ可以移动一个单?br />Ctrl+上下头? 滚动代码屏幕Q但不移动光标位|?br />Ctrl+Shift+L: 删除当前?br />Ctrl+M,M: 隐藏或展开当前嵌套的折叠状?br />Ctrl+M,L: 所有过E设|ؓ相同的隐藏或展开状?br />Ctrl+M,P: 停止大纲昄
Ctrl+E,S: 查看I白
Ctrl+E,W: 自动换行
Ctrl+G: 转到指定?br />Shift+Alt+头? 选择矩Ş文本
Alt+鼠标左按? 选择矩Ş文本
Ctrl+Shift+U: 全部变ؓ大写
Ctrl+U: 全部变ؓ写
代码快捷?/p>
Ctrl+J / Ctrl+K,L: 列出成员
Ctrl+Shift+I格?/ Ctrl+K,P: 参数信息
Ctrl+K,I: 快速信?br />Ctrl+E,C / Ctrl+K,C: 注释选定内容
Ctrl+E,U / Ctrl+K,U: 取消选定注释内容
Ctrl+K,M: 生成Ҏ存根
Ctrl+K,X: 插入代码D?br />Ctrl+K,S: 插入外侧代码
F12: 转到所调用q程或变量的定义
H口快捷?/p>
Ctrl+W,W: 览器窗?br />Ctrl+W,S: 解决Ҏ理?br />Ctrl+W,C: c视?br />Ctrl+W,E: 错误列表
Ctrl+W,O: 输出视图
Ctrl+W,P: 属性窗?br />Ctrl+W,T: d列表
Ctrl+W,X: 工具?br />Ctrl+W,B: 书签H口
Ctrl+W,U: 文大纲
Ctrl+D,B: 断点H口
Ctrl+D,I: xH口
Ctrl+Tab: zdH体切换
Ctrl+Shift+N: 新徏目
Ctrl+Shift+O: 打开目
Ctrl+Shift+S: 全部保存
Shift+Alt+C: 新徏c?br />Ctrl+Shift+A: 新徏?/p>