UDP协议无连接,不存在onConnect, onClose等事件,数据包发出后,对方是否收到也无法得知。UDP数据包有界,因而也不需要Parser::input检测边界。但是Parser::decode/encode也是有意义的:
decode可以把数据包转换成我们便于处理的格式。
encode可以把响应结果转成字节流格式。
app/UdpHandler.php
<?php
namespace app;
use beyoio\UdpMessageEvent;
class UdpHandler extends \beyoio\Handler
{
//当收到udp数据包时,此方法被调用。
public function onUdpMessage(UdpMessageEvent $event)
{
$event->message; //客户发送的数据包内容,具体格式与对应Parser::decode有关
$event->local; //服务器地址(ip:port)
$event->peer; //对方地址(ip:port)
$event->sender; //!!!当前listenner实例
//处理完毕,向客户端发送数据
//$flag含义参阅stream_socket_sendto函数
//$raw发送前是否进行封包处理
$this->sendto($event, $replyMessage, $flag, $raw);
}
}
Handler收到的消息 $event->message格式,与Parser::decode返回的类型相同。
config/main.php
'components'=>[
'server'=>[
'listenners'=>[
'seny' =>[
'listen' => 'udp://0.0.0.0:7512',
'parser' => 'app\UdpParser',
'handler' => 'app\UdpHandler'
]
]
]
]
Linux的syslog用于接受本机或其它节点的日志信息,它可以作为客户端以日志中继器的角色存在,也可以作为日志服务器,接收其它客户端的日志信息。
我们通过Linux系统命令或是syslog函数产生系统日志,本质上是通过unix socket和本机日志服务器通讯,可以用以下命令验证:
[root@sl ~]# netstat -npl | grep syslog
udp 0 0 0.0.0.0:514 0.0.0.0:* 1099/rsyslogd
[root@sl ~]# strace logger "hello syslog"
socket(PF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 1
connect(1, {sa_family=AF_LOCAL, sun_path="/dev/log"}, 110) = 0
sendto(1, "<13>Sep 8 20:55:22 root: hello "..., 38, MSG_NOSIGNAL, NULL, 0) = 38
[root@sl ~]# file /dev/log
/dev/log: socket
可见,产生系统日志信息,就是向/dev/log套接字发送日志消息。SOCK_DGRAM指明了是用户数据报文协议(无连接,不可靠、固定最大长度)。
即syslog监听了两个套接字:
/dev/log unix domain socket, 基于UDP
0.0.0.0:514 UDP端口
unix:// 提供了在 UNIX 域中对套接字流连接的访问。udg:// 提供了替代的传输器以用户数据报协议(UDP)来访问 UNIX 域套接字。
也就是unix://是基于连接的(类似TCP), udg://基于无连接的udp传输协议。
要实现这样的一个服务器,我们首先要弄清楚其数据包格式。
http://www.ietf.org/rfc/rfc3164.txt
beyod自带了syslog服务器,消息格式定义在beyoioprotocolsyslogMessage中,一个syslog日志由以下字段组成:
日志消息来源设备的标识, 值范围目前为0~23
值 | 说明 |
---|---|
0 | kernel messages |
1 | user-level messages |
2 | mail system |
3 | system daemons |
4 | security/authorization messages |
5 | messages generated internally by syslogd |
6 | line printer subsystem |
7 | network news subsystem |
8 | UUCP subsystem |
9 | clock daemon |
10 | security/authorization messages |
11 | FTP daemon |
12 | NTP subsystem |
13 | log audit |
14 | log alert |
15 | clock daemon (note 2) |
16 | local use 0 (local0) |
17 | local use 1 (local1) |
18 | local use 2 (local2) |
19 | local use 3 (local3) |
20 | local use 4 (local4) |
21 | local use 5 (local5) |
22 | local use 6 (local6) |
23 | local use 7 (local7) |
日志消息的严重程度
值 | 说明 |
---|---|
0 | Emergency: system is unusable |
1 | Alert: action must be taken immediately |
2 | Critical: critical conditions |
3 | Error: error conditions |
4 | Warning: warning conditions |
5 | Notice: normal but significant condition |
6 | Informational: informational messages |
7 | Debug: debug-level messages |
日志消息产生的时间,使用GMT时间格式
日志来源主机名。
日志消息内容
典型的格式如:
<13>Oct 22 10:52:12 localhost hello, syslog
<13> 指明了消息来源设备和严重程度,算法为:
serverity = 13 % 8 = 5
facility = 13-5 = 8
Oct 22 10:52:12 是消息产生的时间
localhost是消息来源主机名
hello, syslog 消息内容
服务器配置:
config/main.php
//...
'components'=>[
'server'=>[
//...
'listenners'=>[
'syslog-udg'=>[
'listen' => 'udg://dev/mylog',
'parser' => 'beyod\protocol\syslog\Parser'
],
'syslog-udp'=>[
'listen' => 'udp://0.0.0.0:514',
'parser' => 'beyod\protocol\syslog\Parser'
]
]
]
]
需要自行编写Handler负责消息的最终存储或处理。