使用 Perl 6 发送数据到 Socket

While programming in Spark Streaming, I’d like to send some fake data to socket. although the command nc -lk 9999 is useful, but you have to type the data manually!

With Perl 6’s IO::Socket::Async module, I can easily send data to socket continuously.

In the server side, I listen a port on 3333, I will print the current time every second, every 5 seconds, skip the report of time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
my $vin = 'LSJA0000000000091';
my $last_meter = 0; # 当前里程数

react {
whenever IO::Socket::Async.listen('0.0.0.0', 3333) -> $conn {
react {
my Bool:D $ignore = True;

whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}

whenever Supply.interval(1) {
next if $ignore;
$conn.print: sprintf("\{'vin':'%s','createTime':%s,'mileage':%s}\n", $vin, DateTime.now.posix, $last_meter++);
}

whenever signal(SIGINT) {
say "Done.";
done;
}
}
}
CATCH {
default {
say .^name, ': ', .Str;
say "handled in $?LINE";
}
}
}

Awesome, almost less than 30 lines code.

In the client side, I use telnet 0.0.0.0 3333, which will output something like this:

img

One more thing, I want to save the source data before send to socket port. So i open a file handle in the first whenever block:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
my $vin = 'LSJA0000000000091';
my $last_meter = 0; # 当前里程数

react {
whenever IO::Socket::Async.listen('0.0.0.0', 3333) -> $conn {
my $fh = open 'events.txt', :w;
react {
my Bool:D $ignore = True;

whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}

whenever Supply.interval(1) {
next if $ignore;
$fh.print: sprintf("\{'vin':'%s','createTime':%s,'mileage':%s}\n", $vin, DateTime.now.posix, $last_meter++);
$conn.print: sprintf("\{'vin':'%s','createTime':%s,'mileage':%s}\n", $vin, DateTime.now.posix, $last_meter++);
}

whenever signal(SIGINT) {
say "Done.";
$fh.close;
done;
}
}
}
CATCH {
default {
say .^name, ': ', .Str;
say "handled in $?LINE";
}
}
}

type telnet 0.0.0.0 3333 in shell, watch the output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Trying 0.0.0.0...
Connected to 0.0.0.0.
Escape character is '^]'.
{'vin':'LSJA0000000000091','createTime':1542876852,'mileage':1}
{'vin':'LSJA0000000000091','createTime':1542876853,'mileage':3}
{'vin':'LSJA0000000000091','createTime':1542876854,'mileage':5}
{'vin':'LSJA0000000000091','createTime':1542876855,'mileage':7}
{'vin':'LSJA0000000000091','createTime':1542876856,'mileage':9}
{'vin':'LSJA0000000000091','createTime':1542876867,'mileage':11}
{'vin':'LSJA0000000000091','createTime':1542876868,'mileage':13}
{'vin':'LSJA0000000000091','createTime':1542876869,'mileage':15}
{'vin':'LSJA0000000000091','createTime':1542876870,'mileage':17}
{'vin':'LSJA0000000000091','createTime':1542876871,'mileage':19}
{'vin':'LSJA0000000000091','createTime':1542876882,'mileage':21}
{'vin':'LSJA0000000000091','createTime':1542876883,'mileage':23}
{'vin':'LSJA0000000000091','createTime':1542876884,'mileage':25}
{'vin':'LSJA0000000000091','createTime':1542876885,'mileage':27}
{'vin':'LSJA0000000000091','createTime':1542876886,'mileage':29}

The mileage column looks a little weird, so the column in the events.txt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{'vin':'LSJA0000000000091','createTime':1542876852,'mileage':0}
{'vin':'LSJA0000000000091','createTime':1542876853,'mileage':2}
{'vin':'LSJA0000000000091','createTime':1542876854,'mileage':4}
{'vin':'LSJA0000000000091','createTime':1542876855,'mileage':6}
{'vin':'LSJA0000000000091','createTime':1542876856,'mileage':8}
{'vin':'LSJA0000000000091','createTime':1542876867,'mileage':10}
{'vin':'LSJA0000000000091','createTime':1542876868,'mileage':12}
{'vin':'LSJA0000000000091','createTime':1542876869,'mileage':14}
{'vin':'LSJA0000000000091','createTime':1542876870,'mileage':16}
{'vin':'LSJA0000000000091','createTime':1542876871,'mileage':18}
{'vin':'LSJA0000000000091','createTime':1542876882,'mileage':20}
{'vin':'LSJA0000000000091','createTime':1542876883,'mileage':22}
{'vin':'LSJA0000000000091','createTime':1542876884,'mileage':24}
{'vin':'LSJA0000000000091','createTime':1542876885,'mileage':26}
{'vin':'LSJA0000000000091','createTime':1542876886,'mileage':28}

because $last_meter++ increased twice. I’d better use ⚛++ instead.

Perl 6 Is Writing For Fun, that is, -OFun.