2010年2月28日星期日

485总线在电能表使用中的常见问题及分析--

485总线在电能表使用中的常见问题及分析--

1 在电能表中的应用
由于历史的原因,我国在制定DL/T614-1997《电子式多功能电能表》及 DL/T645-1997《电子式多功能电能表通讯协议》时将RS-485标准串行通讯接口作为电表的通讯接口,并详细地定义了物理层、链路层、应用层, 结束了以前电表厂家规约各不兼容、互相不能抄的尴尬局面。各电表厂家遵循相同的协议标准对电表进行读写操作,简化了电表抄表应用及维护的工作量。使得国内 的智能电表基本上可以做到互联互通。但是目前国内的485抄表还存在一些问题,主要是通信成功率低、不能做到即连即通、易损坏等。
2 物理层、链 路层及数据传输
2.1 物理层
A)共模输入电压:-7V~+12V。
B)差模输入电压:大于0.2V。
C) 三态方式输出。
D)半双工通信方式。
E)驱动能力不小于32个同类接口。
F)总线是无源的,由费率装置 或数据终端提供电源。
G)逻辑“1”以A、B两线间的电压差为+(2~6)V表示;逻辑“0”以两线间的电压差为-(2~6)V表示。
2.2  链路层及数据传输
通讯链路的建立与解除由主站发出的信息帧来控制,帧的组成如表:
由上表可知,帧由起始符、地址域、 控制码、数据长度、数据域、校验码及结束符等7个域组成,每部分由若干字节组成。
DL/T645-1997规定,在发送帧信息之前,先发 送1~4个字节FEH,其目的是预先拉高控制总线,以唤醒接收方,保障帧信息的顺利接收。
DL/T645-1997规定了主?从结构的半 双工通讯方式。每次通讯都是由主站向从站发出请求命令帧开始,从站根据要求作出响应。收到命令帧后的响应延时称作帧间延时 Td:20ms≤Td≤500ms。字节之间停顿时间称作字节间延时Tb:Tb≤500ms。如图1所示:
3 RS485在电表通讯中 的常见问题及解决方案
3.1 收发时序不匹配
现象1:485通讯不成功,用逻辑分析仪查看,发送的码字正确,电能表返回码字也符 合规约。再细看,主站发送的码字的最后一位同电能表应答的数据帧的第一位之间几乎没有停顿。
分析:由于485总线是一个半双工的通讯方 式,收和发不能同时进行,从发送完成到变为接收状态,无论是软件的处理抑或是硬件的切换都需要一定的延时,因此DL/T645规定帧间延时 Td:20ms≤Td≤500ms,主要是给发送方一个由发转为收的时间,保证接收方返回的数据能完整的被接收。而有些电能表,尤其是一些早期的多功能表 对此考虑不够,在接收到主站的请求命令帧后,未进行帧响应延时,就立刻发送应答帧,而此时主站还处于发送状态,等主站返回到接收状态时,电能表前面的码字 已发送完,主站接收到的应答数据帧不完整引起通信失败。
现象2:当主站对某块表连续抄几帧数据时,第一帧通讯成功,第二帧开始电表不回应 答帧。
分析:同样的道理,电表的485由发转为收也需要延时,而有的主站软件编程时,没有考虑,接收完一帧数据后没有延时或延时不够就又 开始抄下一帧,而此时电表还没有回到接收状态,通讯失败。在这里我们建议通信双方在编程时都必须严格遵守DL/T645所规定的帧间延时,并留有余量,具 体应用时可取一个中间值,如100ms。
3.2 判断帧起始符出错
对于电能表485总线来讲,它是一种数字异步通信方式。异步通 信不象同步通信,其没有专门的同步信号进行同步,接收方无法准确判知哪一个字节是一帧数据通信的开始,因此DL/T645中规定68H作为帧起始符(帧同 步码),代表一帧数据的开始。有些主站和电能表在软件编程时考虑得比较理想,接收数据时未按照DL/T645中规定68H来判定数据帧的开始,而是呆板的 以接收到的第一个字符作为帧起始标志;如果电表在此帧数据之前发了几个FEH,其接收到的数据将会出现同步错误。另外,如总线上平时有干扰信号存在,导致 485芯片不停地收到诸如FCH、DEH这样杂乱数据;当总线上有正常信号产生时,由于干扰信号比较小的原因,其对通信并无太大的影响,但对接收方来讲, 其接收正确数据帧前会混有若干个字节的杂乱数据,由于同步处理不当,通讯也会失败。通常的做法是每接收一个字节都要判是否是68H,若不是则丢掉该字节, 然后继续往下判,直到收到68H才启动一帧数据的接收。
3.3 帧奇偶校验位/帧结束符不合理
目前看来,由于这个原因引起485 通信不成功占有很大的比例。我们知道,在485通信时,对于接收到的数据一般都会按收、发双方事先约定的奇偶校验方式进行数据检错,并将错误的数据帧剔 除,等待发送方重发。这种ARQ的通信方式本身是无可厚非的,但是有的软件人员在编程时考虑问题不够全面,在判断一帧结束处理时,没有根据所收数据帧的长 度和结束符“16H”及时地将数据接收任务结束,而是依据多长时间内收不到新的一个字节数据来认为一帧已收完。这种处理方法在下面这种情况下就会导致通信 失败。
众所周知,RS485芯片的接收灵敏度为±200mV,即当电压UA?UB≥200mV时,输出逻辑 “1”;UA?UB≤-200mV时,输出逻辑“0”。当-200mV<UA?UB<200mV时,输出不确定。这样一来,当总线上所有的485芯片均处 于接收状态时,总线处于高阻状态,此时A、B间的压差为0V,芯片输出处于不定状态,可能输出“1”,也可能输出“0”,而且状态会随着时间而变化。如果 输出为“0”,在某些时候则会导致通信失败。我们知道,电能表在发送完应答帧后,一般会马上从发送状态转换到接收状态。正常情况应该是:主站的485芯片 收完最后一个字节的停止位后继续保持为“1”(波形见图2),而有的485芯片则可能跳变保持为“0”(波形见图3),UART(通用异步收发器)则认为 又收到一个字节00H,且很有可能校验和是错的,这样接收软件可能会判断到一个字节校验位出错,而将前面接收完全正确的一帧丢掉,造成通信失败。

FROM: http://www.any17.com/newscenter/new/gongl/2006090308084321.html

2010年1月6日星期三

VGA analogue display connector

ePanorama.net - VGA analogue display connector: "VGA analogue display connector

Nearly all modern PC graphics cards use the same 15 pin conenctor that the original IBM VGA card used. The connector is not very suitable for high resolution graphics because it does not have a well defined impedance characteristics like BNC connectors. 15 pin VGA connector is still commonly used because it is so popular that it is hard to sell product without it.

Pin numbering in female connector

VGA connector picture

Pinout

1 Red out *
2 Green out *
3 Blue out *
4 Monitor ID 2 in
5 Ground
6 Red return
7 Green return
8 Blue return
9 no pin
10 Sync return
11 Monitor ID 0 in
12 Monitor ID 1 in
13 Horizonal Sync out
14 Vertical Sync out
15 reserved (monitor ID 3)

Signals marked with * are analogue 0.7V p-p positive signals to 75 ohm load. All other signals are TTL level signals.

Here is an ASCII pinout diagram for those who prefer it:

6
1 Red (Analog) 6 Red Return 11 (ID0) GND (Color) 11. . . 1
2 Green (Analog) 7 Green Return 12 (ID1) NC (Color) . . .
3 Blue (Analog) 8 Blue Retuen 13 Horzontal Sync . . .
4 Reserved 9 No Connect 14 Vertical Sync . . .
5 Ground 10 Ground 15 No Connect . . .
15 10 5

Monitor ID detection pin assignments

4 11 12
ID2 ID0 ID1

n/c n/c n/c no monitor
n/c n/c GND Mono monitor which does not sopport 1024x768
n/c GND n/c Color monitor which does not support 1024x768
GND GND n/c Color monitor which supports 1024x768

GND menas connected to ground
n/c means that the pin has not bee connected anywhere

This monitor type detection is becoming more and more obsolete nowadays, because more and mode intelligence is integrated to the monitor. New plug-and-play monitors communicate with the computer according to VESA DDC standard.

VESA DDC

VESA Display Data Channel is a method for integrating digital interface to VGA conenctor to be able the monitor and grapahics card to communicate. There are two different levels of DDC: DDC1 and DDC2.

DDC1

DDC1 allows the monitor to tell it's parapeters to the computer. The following VGA card connector pins had to be changed to allow DDC1 fuctions:

pin new function
9 Optional +5V output from graphics card
12 Data from display
14 Standard vertical sync signal which works also as data clock
15 Monitor ID3

When grpahics card detects data on data-line it starts to read the data coming from the monitor syncronous to vertical sync pulse. Vertical sync pulse frequency can be increased up to 25 KHz for the time of the data transfer if a DDC1 compliant monitor is found (be sure not to send those high frequencies to non DDC1 monitors!).

DDC2

DDC2 allows bidirectional communication: monitor can tell it's parameters and computer can adjust monitor settings. The bidirectional data bus is a syncronous data bus similar to Access Bus and is based on I2C technology. Tho following pins had to be changed to to enable DDC2 to work:

pin new function
9 Optional +5V output from graphics card
12 Bidirectional data line (SDA)
15 Data clock (SLC)

The signals in the data bus are standard I2C signals. The computer provides 15 kohm pullup for the SDA and SLC lines. Monitor must provide 47 kohm pull-up on SCLK line.

NOTE: If the optional +5V power output pin is used, a special DDC/VGA connector must be used to to provide proper sequencing. The +5V output voltage must be withing +/-5% range and tha card must be able to supply at least 300 mA current (maximum 1A).

VESA DPMS power saving

VESA has defined a standard method for computer to tell monitor when to go to power saving mode. This power saving mode is controlled by changing the sync signals according the table below:

NORMAL STANDBY SUSPENDED OFF
H-sync On Off On Off
V-sync On On Off Off
Power level 100% 80% <30W <8W"

2009年8月20日星期四

用PHP程序实现支持页面后退的两种方法 - php编程技术及高级应用 - PHP论坛 PHP招聘,PHP教程,PHP代码,打造国内领先PHP技术社区!

用PHP程序实现支持页面后退的两种方法 - php编程技术及高级应用 - PHP论坛 PHP招聘,PHP教程,PHP代码,打造国内领先PHP技术社区!: "用PHP程序实现支持页面后退的两种方法
在开发过程中,往往因为表单出错而返回页面的时候填写的信息都不见了,为了支持页面回跳,可以通过两种方法实现。

第一,使用Header方法设置消息头Cache-control
引用:
header('Cache-control: private, must-revalidate'); //支持页面回跳
第二,使用session_cache_limiter方法
引用:
//注意要写在session_start方法之前
session_cache_limiter('private, must-revalidate');


补充:
Cache-Control消息头域说明
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if- cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must- revalidate、proxy-revalidate、max-age。各个消息中的指令含义如下:

Public指示响应可被任何缓存区缓存。

Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。

no-cache指示请求或响应消息不能缓存

no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。

max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。

min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。

max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。



关于表单刷新

问:为什么我在点击浏览器的后退按钮后,所有字段的信息都被清空了?

答:这是由于你在你的表单提交页面中使用了 session_start 函数。该函数会强制当前页面不被缓存。解决办法为,在你的 Session_start 函数后加入 header('Cache-control: private'); 注意在本行之前你的PHP程序不能有任何输出。

补充:还有基于session的解决方法,在session_start前加上
引用:
session_cache_limiter('nocache');// 清空表单
session_cache_limiter('private'); //不清空表单,只在session生效期间
session_cache_limiter('public'); //不清空表单,如同没使用session一般

可以在session_start();前加上 session_cache_limiter('private,max-age=10800');"

有人正链接到我服务器上的图像,如何阻止? - Blogger 帮助

有人正链接到我服务器上的图像,如何阻止? - Blogger 帮助: "有人正链接到我服务器上的图像,如何阻止?
打印

Blogger 仅提供创建内容的工具,而不充当与该内容有关的调解人。我们允许用户创建 Blog,但我们对这些网页的内容不宣称任何权利。如果对方的电子邮件地址列于网页上,我们建议您直接与作者联系,以解决此问题。

另外,以下文章中还介绍了一些保护您的图片不被他人链接的方法,您可以(而且应该)尝试一下:

* Apache-Sever.com,'防止图片'被盗''
* Webmaster World 讨论帖,'使用 Htaccess 防止图片链接'

有关应用这些技巧的问题,请联系您的 Web 服务提供商。"

2008年12月28日星期日

同步I/O(阻塞I/O),异步I/O(非阻塞)·百家电脑学院

同步I/O(阻塞I/O),异步I/O(非阻塞)·百家电脑学院: "同步I/O(阻塞I/O),异步I/O(非阻塞)

同步I/O(为什么叫做阻塞I/O),异步I/O(为什么叫做非阻塞)?写进去的和读出来的内容是一致叫做同步,而阻塞时是指当写/读完成时,要等待读/写在物理上完成后,才返回,这样才能保持读写或写读的一致性(因为这样才认为阻塞是同步吗?)

[ 本帖最后由 SybaseLU 于 2007-6-11 10:33 编辑 ]

rrrrrrrr8 2007-6-11 02:35
我只是很清楚什么叫阻塞和非阻塞.
I/O同步异步与阻塞非阻塞之间是什么关系,个人认为还不能直截划等号.请高手回答!

wflyfox 2007-6-11 03:03
阻塞模式下,调用accept,connect,read等函数会阻塞进程直到成功或者失败
非阻塞方式下,调用阻塞函数时(如read),如果没有数据可读,立即返回EAGAIN,不会阻塞在函数调用。

什么叫同步、异步呢?
请解答

SybaseLU 2007-6-11 03:56
1 众所周知,人们常常将read/write/...认为是阻塞I/O【不是还可以通过打开模式设定是NOBLOCK或是BLOCK吗?为什么直接说他们是阻塞I/O呢?】,而标准的ANSI 的fread/fwrite..都是非阻塞I/O【等待在物理上完成实际的I/O操作】
2 如果在一个进程中至少有2个以上的描述符,假设是fd1, fd2,如果需要将fd1的输入送到fd2上,将fd2的输出送到fd1的输入上,这时进程同时对2个输入和2个输出进行读写,采用非阻塞read/write, 他们如何被阻塞,而不得不采用select多路转换呢?

xhl 2007-6-11 04:19
原帖由 wflyfox 于 2007-6-11 11:03 发表
阻塞模式下,调用accept,connect,read等函数会阻塞进程直到成功或者失败
非阻塞方式下,调用阻塞函数时(如read),如果没有数据可读,立即返回EAGAIN,不会阻塞在函数调用。

什么叫同步、异步呢?
请解答 [/quote]


同步,异步的概念本来是通信领域的, 很难解释清楚, 但我肯定他跟阻塞非阻塞完全没有任何关系。

在这里的同步异步, 我个人的理解是函数调用的时候的同步异步。

其实同步方式很好理解, 例如你调用一个function, 当这个function执行完后, 这个方法实现的功能已经完成。这里往往会跟阻塞混淆,其实是因为你采用了同步方式执行代码, 才阻塞了你的thread或者process. 而不是因为阻塞,才叫同步。

异步方式就不提供这种保证, 当你用异步方式调用一个function的时候,这个方法会马上返回,事实上多数情况
下这种function call只是向某个任务执行体提交一个任务而已。 而你的主thread可以继续执行其他的事情, 不必等待(阻塞), 而当那个任务执行体执行完你提交的这个任务后,它会通过某种方法callback给你的thread, 告诉你,你的这个任务已经完成。


实际上,在目前的应用中, 很少有真正实现异步IO的(AIO), 听说(Windows 完成端口跟bsd kqueue实现了, 只是听说而已), 而通过select/poll等实现的不能算是AIO,只能说是个类似的或者是假冒的。。

因为用select/poll实现的情况下,他们多半都是把调用thread作为执行体thread的。

上面完全是个人理解,欢迎指正!

flw2 2007-6-11 04:26
我觉得阻塞和非阻塞主要是指读,而同步和异步是说写

非阻塞就是说: 如果没有数据我宁愿不要了,不要让我等,我还要干别的,我一会再来看有没有。
阻塞就是: 如果没有我要的数据,我的程序无法继续下去,所以没有就等等吧,没有关系,我没别的事情

同步就是写的时候真写了,而不是透明地放在某个地方。
异步就刚好相反了
不管是那个层次,比如fflush fsync等,都是说不要给我缓存,比如写一个优盘上的文件,优盘马上要被拔掉,那么写完之后很可能需要同步一下(虽然其实umount也肯定会同步)

zx_wing 2007-6-11 05:07
[quote]原帖由 xhl 于 2007-6-11 12:19 发表



同步,异步的概念本来是通信领域的, 很难解释清楚, 但我肯定他跟阻塞非阻塞完全没有任何关系。

在这里的同步异步, 我个人的理解是函数调用的时候的同步异步。

其实同步方式很好理解, 例如你调用一 ... [/quote]
大概如此,不过只讲了概念,没有讲细节。我就简单补充一下linux中SIO(同步IO)和AIO(异步IO)机制
1.read/write:
对于read操作来说,它是同步的。也就是说只有当申请读的内容真正存放到buffer中后(user mode的buffer),read函数才返回。在此期间,它会因为等待IO完成而被阻塞。研究过源码的朋友应该知道,这个阻塞发生在两个地方:一是read操作刚刚发起,kernel会检查其它进程的need_sched标志,如果有其它进程需要调度,主动阻塞read操作,这个时候其实I/O操作还没有发起。二是I/O操作发起后,调用lock_page对已经加锁的页面申请锁,这时由于页面已经加锁,所以加锁操作被阻塞,从而read操作阻塞,直到I/O操作完成后页面被解锁,read操作继续执行。所以说read是同步的,其阻塞的原因如上。
对于write操作通常是异步的。因为linux中有page cache机制,所有的写操作实际上是把文件对应的page cache中的相应页设置为dirty,然后write操作返回。这个时候对文件的修改并没有真正写到磁盘上去。所以说write是异步的,这种方式下write不会被阻塞。如果设置了O_SYNC标志的文件,write操作再返回前会把修改的页flush到磁盘上去,发起真正的I/O请求,这种模式下会阻塞。
2.Direct I/O
linux支持Direct I/O, 以O_DIRCET标志打开的文件,在read和write的时候会绕开page cache,直接使用user mode的buffer做为I/O操作的buffer。这种情况下的read和write直接发起I/O操作,都是同步的,并会被阻塞。
3.AIO
目前大多数的linux用的AIO是基于2.4内核中的patch,使用librt库中的接口。这种方式实现很简单,就是一个父进程clone出子进程帮其做I/O,完成后通过signal或者callback通知父进程。用户看来是AIO,实质还是SIO。linux kernel中AIO的实现概念类似,只不过是以一组kernel thread去做的。这些kernel thread做I/O的时候使用的是和Direct I/O相同的方式。
4.mmap()
抛开它中讲vm_area和page cache映射在一起的机制不说。真正发起I/O时和read、write使用的是相同的机制,同步阻塞。


就简单的介绍一下,欢迎指正。

zx_wing 2007-6-11 05:10
[quote]原帖由 flw2 于 2007-6-11 12:26 发表
我觉得阻塞和非阻塞主要是指读,而同步和异步是说写

非阻塞就是说: 如果没有数据我宁愿不要了,不要让我等,我还要干别的,我一会再来看有没有。
阻塞就是: 如果没有我要的数据,我的程序无 ...



>>我觉得阻塞和非阻塞主要是指读,而同步和异步是说写
同步、异步主要是指你读/写的内容和目标磁盘上对应的block时不时一样的
阻塞、非阻塞是指发起操作的函数是马上返回,还是被block直到操作完成"

2008年12月24日星期三

PHP的Socket函数参考 - ◇Linux程序设计交流区 - LPI中文论坛 ——— 全球最大的LPI认证交流社区! - Powered by Discuz!

PHP的Socket函数参考 - ◇Linux程序设计交流区 - LPI中文论坛 ——— 全球最大的LPI认证交流社区! - Powered by Discuz!: "PHP的Socket函数参考
这些Socket函数直接跟互联网的协议进行发送信息。相对于fopensock的流来讲,他们操作在一个比较底层的级别。通常,他们都是对C 函数进行封装,并且名称都类似。如果你有使用C进行socket编程的经验,那么使用这些函数将是非常熟练的。我们这里不讨论特别详细的socket编程。
使用这些函数能够解决高层级别函数所不能解决的难题。使用这些函数能够实现类似fopen的功能,你也许有很多方法来实现socket的功能,比如在PHP中使用CLI(Command-line Interface)来实现的Internet守护进程。
resource socket_accept(resource socket)
在你的脚本服务器端中,使用socket_accept接受一个进入的连接。你必须首先产生一个socket,绑定它到一个名字,并且设置它监听一个端口。在块模式中,socket_accept将产生一个唯一接受后的连接。在非块模式中,它没有建立连接则返回false。另外,当你有了一个新的socket资源后就能够进行读写操作。
下面我们将示范一个简单的回显服务器端。它运行在CLI(命令行)下面,它在12345端口等待客户端的连接。
socket_accept
<?php
set_time_limit(0);
//create the socket
if(($socket = socket_create(AF_INET, SOCK_STREAM, 0)) < 0){
print('Couldn't create socket: ' . socket_strerror(socket_last_error()) . '\n');
}
//bind it to the given address and port
if(($error = socket_bind($socket, gethostbyname($_SERVER['HOSTNAME']), 12345)) < 0){
print('Couldn't bind socket: ' . socket_strerror(socket_last_error()) . '\n');
}
if(($error = socket_listen($socket, 5)) < 0){
print('Couldn't list on socket: ' .
socket_strerror(socket_last_error()) . '\n');
}
while(TRUE){
//wait for connection
if(($accept = socket_accept($socket)) < 0){
print('Error while reading: ' . socket_strerror($message) . '\n');
break;
}
//send welcome message
socket_write($accept, 'Connection accepted\n');
print(date('Y-m-d H:i:s') . ' STATUS: Connection accepted\n');
ob_flush();
while(TRUE){
//read line from client
if(FALSE === ($line = socket_read($accept, 1024))){
print('Couldn't read from socket: ' .
socket_strerror(socket_last_error()) . '\n');
break 2;
}
if([email=%21@socket_write%28$accept]!@socket_write($accept[/email], 'ECHO: $line')){
print(date('Y-m-d H:i:s') . ' STATUS: Connection interrupted\n');
break;
}
print(date('Y-m-d H:i:s') . ' READ: $line');
ob_flush();
}
socket_close($accept);
}
?>

bool socket_bind(resource socket, string address, integer port)
这个socket_bind()把一个socket资源绑定在一个地址上。这个socket必须由socket_create()函数返回的一个资源。这个地址必须是一个IP地址或者是一个保存Unix socket的路径。如果是运行在Internet上的socket,你还必须提供一个端口。
socket_clear_error(resource socket)
这个函数能够清除制定socket的错误,如果没有指定参数,那么将清除所有socket的错误。
socket_close(resource socket)
socket_close函数关闭一个socket并且清除该socket所占用的内存资源。
boolean socket_connect(resource socket, string address, integer port)
这个函数创建一个客户端到一个端口或者socket的连接。你必须提供一个由socket_create产生的socket。这个address参数必须到一个socket的路径或者是一个IP地址。如果是后者,还必须跟一个数字的端口号。
下面例子演示了使用UDP协议的连接到游戏服务器然后获取信息的过程。
socket_connect
<?php
//create UDP socket
if(($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) < 0){
print('Couldn't create socket: ' .
socket_strerror(socket_last_error()) . '\n');
}
//timeout after 5 seconds
socket_set_option($socket, SOL_SOCKET,
SO_RCVTIMEO, array('sec'=>5,'usec'=>0));
//connect to the RtCW master server
if(!socket_connect($socket, 'wolfmaster.idsoftware.com', 27950)){
print('Couldn't connect: ' .
socket_strerror(socket_last_error()) . '\n');
}
//send request for servers
socket_write($socket, '\xFF\xFF\xFF\xFFgetservers\x00');
//get servers
$server = array();
while(FALSE !== ($line = @socket_read($socket, 4096))){
//parse data
for($i=22; ($i+5) < strlen($line); $i += 7){
$ip = ord(substr($line, $i+1, 1)) . '.' .
ord(substr($line, $i+2, 1)) . '.' .
ord(substr($line, $i+3, 1)) . '.' .
ord(substr($line, $i+4, 1));
$port = (ord(substr($line, $i+5, 1)) * 256) +
ord(substr($line, $i+6, 1));
$server[] = array('ip'=>$ip, 'port'=>$port);
}
}
print('<h1>' . count($server) . ' Servers</h1>\n');
//loop over servers, getting status
foreach($server as $s){
print('<h1>{$s['ip']}:{$s['port']}</h1>\n');
//connect to RtCW server
if(!socket_connect($socket, $s['ip'], $s['port'])){
print('<p>\n' .
socket_strerror(socket_last_error()) .
'\n</p>\n');
continue;
}
//send request for status
socket_write($socket, '\xFF\xFF\xFF\xFFgetstatus\x00');
//get status from server
if(FALSE === ($line = @socket_read($socket, 1024))){
print('<p>\n' .
socket_strerror(socket_last_error()) .
'\n</p>\n');
continue;
}
$part = explode('\n', $line);
//settings are in second line separated by backslashes
$setting = explode('\\', $part[1]);
print('<h2>Configuration</h2>\n');
print('<p>\n');
for($s=1; $s < count($setting); $s += 2){
print('\t\t{$setting[$s]} = {$setting[$s+1]}<br>\n');
}
print('</p>\n');
print('<h2>Players</h2>\n');
$lastPlayer = count($part) - 1;
for($p=2; $p < $lastPlayer; $p++){
$player = explode(' ', $part[$p]);
print('{$player[2]} Score={$player[0]} ' .
'Ping={$player[1]}<br>\n');
}
print('</p>\n');
ob_flush();
}
print('</table>\n');
socket_close($socket);
?>
resource socket_create(integer family, integer socket_type, integer protocol)
socket_create初始化一个socket的结构。第一个参数是一个protocol family,或者域。你必须使用AF_INET来指定一个Internet连接,或者使用AF_UNIX来指定一个Unix socket连接。第二个参数是一个socket的类型,你可以从下面的表中选择。一般情况下,使用SOCK_STREAM来使用TCP协议,UDP协议使用SOCK_DGRAM。第三个参数指定为一个协议。使用SOL_TCP或SOL_UDP来分别对应TCP和UDP协议。还有一个选择是你能够使用 getprotobyname函数来处理。
Socket 类型
常量 描述
SOCK_DGRAM 自动寻址数据包socket
SOCK_RAW RAW协议接口
SOCK_RDM 可靠交换消息
SOCK_SEQPACKET 顺序数据包socket
SOCK_STREAM 流socket
resource socket_create_listen(integer port, integer backlog)
使用socket_create_listen是一种比socket_create更简单的产生一个socket进行监听。这个产生的socket将监听指定的端口,后面可选的参数backlog是设置允许最大的连接数。
boolean socket_create_pair(integer family, integer socket_type, integer protocol, array handles)
socket_create_pair函数产生一对socket连接。首先前三个参数是对一个socket_create的描述,这个handles参数是一个包含两个socket资源的数组。该函数是对C里面socketpair函数的封装。
socket_create_pair
<?php
if(!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $socket)){
print('Couldn't make sockets!\n');
exit();
}
$child = pcntl_fork();
if($child == -1){
print('Couldn't fork!\n');
exit();
}
elseif($child > 0){
//parent
socket_close($socket[0]);
print('Parent: waiting for message\n');
$message = socket_read($socket[1], 1024, PHP_NORMAL_READ);
print('Parent: got message--$message\n');
socket_write($socket[1], 'Hello, Child Process!\n');
pcntl_waitpid($child, $status);
}else{
//child
socket_close($socket[1]);
socket_write($socket[0], 'Hello, Parent Process!\n');
print('Child: waiting for message\n');
$message = socket_read($socket[0], 1024, PHP_NORMAL_READ);
print('Child: got message--$message\n');
exit(0);
}
?>
value socket_get_option(resource socket, integer level, integer option)
socket_get_option函数返回一个下表中所列的一个添加值,你必须提供一个由socket_create产生的socket资源和一个等级。这个获取的socket级别,可以使用SOL_SOCKET来确定这个级别参数。另外,使用协议,比如象SOL_TCP来表示一个TCP协议。这些选项可能是由socket_set_option设置的。
socket_get_options
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
print('SO_BROADCAST: ' .
socket_get_option($socket, SOL_SOCKET,
SO_BROADCAST) . '<br>\n');
print('SO_DEBUG: ' .
socket_get_option($socket, SOL_SOCKET,
SO_DEBUG) . '<br>\n');
print('SO_DONTROUTE: ' .
socket_get_option($socket, SOL_SOCKET,
SO_DONTROUTE) . '<br>\n');
print('SO_ERROR: ' .
socket_get_option($socket, SOL_SOCKET,
SO_ERROR) . '<br>\n');
print('SO_KEEPALIVE: ' .
socket_get_option($socket, SOL_SOCKET,
SO_KEEPALIVE) . '<br>\n');
print('SO_LINGER: ' .
print_r(socket_get_option($socket, SOL_SOCKET,
SO_LINGER), TRUE) . '<br>\n');
print('SO_OOBINLINE: ' .
socket_get_option($socket, SOL_SOCKET,
SO_OOBINLINE) . '<br>\n');
print('SO_RCVBUF: ' .
socket_get_option($socket, SOL_SOCKET,
SO_RCVBUF) . '<br>\n');
print('SO_RCVLOWAT: ' .
socket_get_option($socket, SOL_SOCKET,
SO_RCVLOWAT) . '<br>\n');
print('SO_RCVTIMEO: ' .
print_r(socket_get_option($socket, SOL_SOCKET,
SO_RCVTIMEO), TRUE) . '<br>\n');
print('SO_REUSEADDR: ' .
socket_get_option($socket, SOL_SOCKET,
SO_REUSEADDR) . '<br>\n');
print('SO_SNDBUF: ' .
socket_get_option($socket, SOL_SOCKET,
SO_SNDBUF) . '<br>\n');
print('SO_SNDLOWAT: ' .
socket_get_option($socket, SOL_SOCKET,
SO_SNDLOWAT) . '<br>\n');
print('SO_SNDTIMEO: ' .
print_r(socket_get_option($socket, SOL_SOCKET,
SO_SNDTIMEO), TRUE) . '<br>\n');
print('SO_TYPE: ' .
socket_get_option($socket, SOL_SOCKET,
SO_TYPE) . '<br>\n');
?>

Socket选项表
选项 描述
SO_BROADCAST 允许自动寻址的socket发送和接受广播包
SO_DEBUG 打开socket调试功能,只有root才有权限打开该选项
SO_DONTROUTE 不接受路由包通过网关
SO_ERROR 获取并且清除最后一次的socket错误,这个选项也许不用设置
SO_KEEPALIVE 打开保持激活状态的消息
SO_LINGER Socket_colse和socket_shutdown的中止消息发送超时,该选项使用一个数组,包括l_onoff和l_linger两个键。
SO_OOBINLINE 把数据直接插入到接受缓冲
SO_RCVBUF 限制接受缓冲的最大字节
SO_RCVLOWAT 延迟通过接受一个最小的数据
SO_RCVTIMEO 延迟报告一个接受超时报告,使用数组的两个键:sec和usec
SO_REUSEADDR 允许重新使用本地地址
SO_SNDBUF 限制发送缓冲的最大字节
SO_SNDLOWAT 延迟发送数据到这个协议当接受一个最小的字节
SO_SNDTIMEO 延迟报告超时错误,当发送发送通过一个时间。该选项使用数组的键值:sec和usec
SO_TYPE 获取socket的类型,该选项可能不用设置

boolean socket_getpeername(resource socket, string address, integer port)
socket_getpeername从指定的一个连接中获取地址和端口。如果连接为Unix socket,那么将返回文件系统的路径。
boolean socket_getsockname(resource socket, string address, integer port)
socket_getsockname放置一个名字到socket中,并且加上address和port参数。失败返回false。
(下面的socket_iovec_* 函数不太了解,不敢乱翻译,保留原文)
boolean socket_iovec_add(resource iovector, integer length)
The socket_iovec_add unction adds an I/O vector to the scatter/gather array.
resource socket_iovec_alloc(integer count, …)
The socket_iovec_alloc function returns a resource for handling a collection of I/O vectors. The first argument specifies the number of vectors. Following arguments specify the length of each vector.
boolean socket_iovec_delete(resource iovector, integer position)
The socket_iovec_delete function removes the I/O vector at the given position.
string socket_iovec_fetch(resource iovector, integer position)
The socket_iovec_fetch function returns the value of the specified vector in the I/O vector resource.
boolean socket_iovec_free(resource iovector)
The socket_iovec_free function frees the memory used for an I/O vector resource.
boolean socket_iovec_set(resource iovector, integer position, string value)
The socket_iovec_set sets the value of I/O vector at the given position.
integer socket_last_error(resource socket)
socket_last_error函数返回操作中的任何socket函数产生的最后错误。你也许在上面函数中设置了socket资源的 socket选项在指定的连接上。下面的表列出了返回的错误代码,你同样可以使用soclet_strerror函数来获取详细的错误。使用 socket_clear_error函数清除socket的错误。
Socket错误代码表
常量 描述
SOCKET_E2BIG 参数列表太长
SOCKET_EACCES 没有许可权限
SOCKET_EADDRINUSE 地址已经被使用
SOCKET_EADDRNOTAVAIL 不能解析请求的地址
SOCKET_EADV 广播(广告)错误
SOCKET_EAFNOSUPPORT Address family不支持的协议
SOCKET_EAGAIN 资源暂时不能获得
SOCKET_EALREADY 操作已经在执行
SOCKET_EBADE 无效的交换
SOCKET_EBADF 错误的文件描述符
SOCKET_EBADFD 文件描述符错误的状态
SOCKET_EBADMSG 错误的消息
SOCKET_EBADR 无效的请求描述
SOCKET_EBADRQC 无效的请求代码
SOCKET_EBADSLT 无效的操作位置
SOCKET_EBUSY 驱动或资源繁忙
SOCKET_ECHRNG 信道号码超出范围
SOCKET_ECOMM 发送通讯错误
SOCKET_ECONNABORTED 软件原因导致通行中断
SOCKET_ECONNREFUSED 连接被拒绝
SOCKET_ECONNRESET 连接被相同的socket重置
SOCKET_EDESTADDRREQ 必须需要目标地址
SOCKET_EDQUOT 超出磁盘配额
SOCKET_EEXIST 文件已存在
SOCKET_EFAULT 错误的地址
SOCKET_EHOSTDOWN 主机已关闭
SOCKET_EHOSTUNREACH 没有路由到主机
SOCKET_EIDRM 表示ID被删除
SOCKET_EINPROGRESS 操作正在执行
SOCKET_EINTR 系统调用被阻止
SOCKET_EINVAL 无效的参数
SOCKET_EIO 输入/ 输出错误
SOCKET_EISCONN 传输终端已经连接
SOCKET_EISDIR 是一个目录
SOCKET_EISNAM 是一个指定的类型文件
SOCKET_EL2HLT 级别2已中止
SOCKET_EL2NSYNC 级别2不同步
SOCKET_EL3HLT 级别3已中止
SOCKET_EL3RST 级别3被重置
SOCKET_ELNRNG 连接号超出范围
SOCKET_ELOOP 太多级别的符号连接
SOCKET_EMEDIUMTYPE 错误的媒介类型(中间类型)
SOCKET_EMFILE 太多打开的文件
SOCKET_EMLINK 太多的连接
SOCKET_EMSGSIZE 消息太长
SOCKET_EMULTIHOP 尝试次数太多
SOCKET_ENAMETOOLONG 文件名太长
SOCKET_ENETDOWN 网络已关闭
SOCKET_ENETRESET 网络中断,连接被重置
SOCKET_ENETUNREACH网络不可达
SOCKET_ENFILE 系统中太多打开的文件
SOCKET_ENOANO 没有正极
SOCKET_ENOBUFS 没有可用的缓存空间
SOCKET_ENOCSI 没有可用的CSI结构
SOCKET_ENODATA 没有可用的数据
SOCKET_ENODEV 没有这样的驱动
SOCKET_ENOENT 没有这样的文件或目录
SOCKET_ENOLCK 没有可用的记录锁
SOCKET_ENOLINK 已经有的服务的连接
SOCKET_ENOMEDIUM 没有媒介被找到
SOCKET_ENOMEM 不能分配内存
SOCKET_ENOMSG 没有指定的消息类型
SOCKET_ENONET 设备不在网络上
SOCKET_ENOPROTOOPT 协议不可用
SOCKET_ENOSPC 没有空间在驱动器
SOCKET_ENOSR 超出的流资源
SOCKET_ENOSTR 驱动不是一个流
SOCKET_ENOSYS 函数没有执行
SOCKET_ENOTBLK 块驱动是必须的
SOCKET_ENOTCONN 传输终端没有连接
SOCKET_ENOTDIR 没有一个目录
SOCKET_ENOTEMPTY 目录为空
SOCKET_ENOTSOCK Socket操作在一个非socket上
SOCKET_ENOTTY 不相符的IO控制器
SOCKET_ENOTUNIQ 在网络上名字不是唯一的
SOCKET_ENXIO 没有这样的驱动或地址
SOCKET_EOPNOTSUPP 操作不支持
SOCKET_EPERM 操作不允许
SOCKET_EPFNOSUPPORT Protocol family不支持
SOCKET_EPIPE 失败的管道
SOCKET_EPROTO 协议错误
SOCKET_EPROTONOSUPPORT 协议不支持
SOCKET_EPROTOTYPE Socket上协议错误的类型
SOCKET_EREMCHG 远程地址已改变
SOCKET_EREMOTE 对象是远程的
SOCKET_EREMOTEIO 远程I/O错误
SOCKET_ERESTART 中断的系统调用将要重新开始
SOCKET_EROFS 文件系统为只读
SOCKET_ESHUTDOWN. 传输端点中断不能发送
SOCKET_ESOCKTNOSUPPORT Socket类型不支持
SOCKET_ESPIPE 不合法的检索
SOCKET_ESTRPIPE 流管道错误
SOCKET_ETIME 定时器到时
SOCKET_ETIMEDOUT 连接超时
SOCKET_ETOOMANYREFS 太多连接无法结合
SOCKET_EUNATCH 无法附加协议驱动
SOCKET_EUSERS 太多用户
SOCKET_EWOULDBLOCK 资源暂时无法获得
SOCKET_EXDEV 无效的交叉驱动连接
SOCKET_EXFULL 交换已满

boolean socket_listen(resource socket, integer backlog)
这个socket_listen函数等待从客户端过来的连接,backlog参数设置允许最多等待连接的队列数。
string socket_read(resource socket, integer length, integer type)
socket_read函数从特定的socket中读取指定的字节,如果错误返回false。缺省下,是采用二进制安全的读取模式。你可以外在的设置type参数为PHP_BINARY_READ来改变读取模式。你也可以把type设置为PHP_NORMAL_READ。
boolean socket_readv(resource socket, resource iovector)
socket_readv函数把读取的数据插入到iovector资源中。
integer socket_recv(resource socket, string buffer, integer length, integer flags)
socket_recv函数读取数据插入到缓冲中。Length参数设置最多读取的字节数,flag参数可以使用MSG_OOB或MSG_PEEK。函数返回读取的字节数。
integer socket_recvfrom(resource socket, string buffer, integer length, string host, integer port)
socket_frcvfrom函数读取数据插入到缓存中。Length参数设置获取最多允许接受的字节数。设置flags参数可以为MSG_OOB 或 MSG_PEEK。PHP设置主机和端口参数适当的值能够获取从主机发出的数据。
boolean socket_recvmsg(resource socket, resource iovector, array control, integer length, integer flags, string host, integer port)
socket_recvmsg函数从socket中读取数据并且插入到一个I/O向量资源中。PHP设置control参数是一个具有三个元素的联合数组:cmsg_level, cmsg_type, 和 cmsg_data。Length参数是一个附加在数据中的关于获取数据的长度参数。Flags参数是设置允许值和返回值。在写的时间,PHP无法执行所有的输出常量。PHP设置host和port参数适当的值是为了获取从远程主机中发送的数据。
(Socket_slect函数没有翻译,因为怕词不达意)
integer socket_select(array read, array write, array exception, integer timeout_seconds, integer timeout_microseconds)
The socket_select function waits for changes to sockets. PHP watches the sockets given in the read array for new data coming in. PHP watches the streams given in the write array for being ready to accept more data. PHP watches the streams given in the exception argument for errors. If the number of seconds specified in the timeout_seconds argument passes, the function returns. Use the optional timeout_microseconds argument to specify a timeout less than 1 second.
The socket_select function returns the number of sockets that changed or FALSE if an error occurred. If the call timed out, this function returns zero. It also modifies the given arrays so that they include only those sockets that changed.
If you have no sockets of a particular type to watch, you may pass an empty array or a variable set to NULL.
integer socket_send(resource socket, string buffer, integer length, integer flags)
socket_send函数把写数据到缓冲中,然后插入到连接中。你必须指定一个缓冲最大可写字节数。你同样可以设置flags参数为空,或者为下面联合常量中的一个:MSG_DONTROUTE和 MSG_OOB。函数结束返回已经写的字节数,失败返回false。
boolean socket_sendmsg(resource socket, resource iovector, integer flags, string address, integer port)
socket_sendmsg尝试发送数据到一个socket。它适合无连接的socket。Iovector参数是一个通过 socket_iovec_alloc函数产生的资源。你必须指定flags参数为:NULL, MSG_DONTROUTE, MSG_OOB,或者是两个联合常量。你应当指定一个地址和一个Internet请求的端口。
Socket_sendmsg函数发送数据返回true,但是不能保证数据一定到达。
integer socket_sendto(resource socket, string buffer, integer length, integer flags, string address, integer port)
socket_sendto函数尝试写数据到buffer缓冲中,并且发送给一个socket。它适合大部分无连接的socket。你必须指定 flags为:NULL,MSG_DONTROUTE,MSG_OOB或者是一个两个联合常量。你还应但指定地址和一个请求的端口。
Socket_sendto函数数据发送出去返回true,但是不能保证数据一定到达。

boolean socket_set_block(resource socket)
socket_set_block函数设置socket插入到一个块模式中,这是缺省模式。在块模式中,I/O操作正对于一个完成的请求。
boolean socket_set_nonblock(resource socket)
socket_set_nonblock函数设置socket插入到意个非块模式中。在非块模式中,I/O操作马上返回,即使没有数据。
boolean socket_set_option(resource socket, integer level, integer option, integer value)
socket_set_option函数给socket设置一个选项。Level参数设置一个标志级别的常量。有效的值包括:SOL_SOCKET, SOL_TCP和SOL_UDP。Option参数必须匹配文章上面的Socket选项表中的常量。
boolean socket_shutdown(resource socket, integer how)
socket_shutdown函数关闭一个关于I/O的socket。设置how为0则中止接受数据,设置为1则停止发送数据,设置为2则中止二者操作。
string socket_strerror(integer error)
socket_strerror函数返回一个错误号的详细错误信息。
integer socket_write(resource socket, string buffer, integer length)
socket_write函数写数据到buffer缓冲中然后输出到socket中。你可以指定length参数来指定缓冲的最大字节数。这个函数通常情况下比socket_send更方便。
boolean socket_writev(resource socket, resource iovector)
socket_writev函数通过I/O向量写数据到一个socket中。"

2008年12月22日星期一

UA-NIC-handle组织号申请教程(ORG.UA免费域名)

UA-NIC-handle组织号申请教程(ORG.UA免费域名): "UA-NIC-handle组织号申请教程(ORG.UA免费域名)
来源:互联网 作者:佚名 发布时间:2007-08-05

首先要申请个NIC的个人号或者组织号,推荐组织号
UA-NIC-handle组织号申请方法
有组织号可以一直申请免费的UA米,和Ripn的组织号功能差不多
用组织号或个人号申请UA米,可免费10年
申请地址:https://hostmaster.net.ua/?uanew2
1.在打开页面的右上角选择english使用英文



2.开始注册组织号,注意格式






3.申请成功,回馈信息



4.到邮箱收信,里面有你的组织号密码
查看一封主题为new password的邮件
Quote:

Ваш новый пароль для редактирования регистрационных данных о Вашем nic-handle BNNB: QAUVMTS

Your new password to edit registration data for nic-handle BNNB: QAUVMTS

5.登录https://hostmaster.net.ua/auth/修改密码"