问题
Right now I'm developing a some sort of parser for the messages of the Skypatrol TT8750+ and my threaded TCP server is working. The problem is that it isn't a good approach if there are to many devices connected at the same time. I'm using iodine but I can't make work some code that was given to me. My goal is to receive first a 33bytes message to identify the device and then start to receive 86bytes messages with information of the vehicle.
require 'iodine'
# define the protocol for our service
class TT8750plus
@timeout = 10
def on_open
puts "New Connection Accepted."
# this file is just for testing purposes.
t = Time.now.strftime("%d-%m-%Y %H%M")
file_name = t + '.txt'
@out_file = File.new(file_name, "w+")
# a rolling buffer for fragmented messages
@expecting = 33
@msg = ""
end
def on_message buffer
length = buffer.length
pos = 0
while length >= @expecting
@msg << (buffer[pos, @expecting])
@out_file.puts(@msg.unpack('H*')[0])
length -= @expecting
po += @expecting
@expecting = 86
@msg.clear
end
if(length > 0)
@msg << (buffer[pos, length])
@expecting = 86 - length
end
puts @msg
end
def on_close
@out_file.close
end
end
# create the service instance
Iodine.listen 12050, TT8750plus
# start the service
Iodine.start
And this error appears on every message
New Connection Accepted.
Iodine caught an unprotected exception - NoMethodError: undefined method `+' for nil:NilClass
iodineServer.rb:26:in `on_message'
iodineServer.rb:1:in `on_data'Iodine caught an unprotected exception - NoMethodError: undefined method `+' for nil:NilClass
Also this implementation doesn't get the messages I need These are the first two lines that I got from this implementation:
0021000a0800000000000120202020202038363332383630323034333433373020
0021000a08000000000001202020202020383633323836303230343334333730200056000a08100020202020202038363332383630323034333433373020014b0000
And these are the first two lines from the threaded implementation
0021000a0800000000000120202020202038363332383630323034333433373020
0056000a08100020202020202038363332383630323034333433373020000b00000013090044709bfb8109e400000000001100000000000067eb11090c1512012e970020000000000005000000000005000000000007
0056000a08100020202020202038363332383630323034333433373020010b00000013090044709bfb8109e400000000001200000000000067eb11090c1512042e970020000000000005000000000005000000000008
回答1:
This looks like a variation of the untested code I posted earlier.
It seems the issue is with a spelling mistake in the code (probably mine?).
The po += ...
should have been pos += ...
require 'iodine'
# define the protocol for our service
class TT8750plus
@timeout = 10
def on_open
puts "New Connection Accepted."
# this file is just for testing purposes.
t = Time.now.strftime("%d-%m-%Y %H%M")
file_name = t + '.txt'
@out_file = File.new(file_name, "w+")
# a rolling buffer for fragmented messages
@expecting = 33
@msg = ""
end
def on_message buffer
length = buffer.length
pos = 0
while length >= @expecting
@msg << (buffer[pos, @expecting])
@out_file.puts(@msg.unpack('H*')[0])
length -= @expecting
pos += @expecting # the spelling mistake was here
@expecting = 86
puts "wrote:", @msg
@msg.clear
end
if(length > 0)
@msg << (buffer[pos, length])
@expecting = 86 - length
end
puts("Waiting for more data:", @msg) unless @msg.empty?
end
def on_close
@out_file.close
end
end
# create the service instance
Iodine.listen 12050, TT8750plus
# start the service
Iodine.start
Again, lacking an emulation for the Skypatrol TT8750+, I can't test the code. But it should be possible to follow error messages to slowly track down these types of issues.
P.S.
To protect from exceptions, consider using Ruby's:
begin
# code
rescue => e
# oops something happened. i.e.
puts e.message, e.backtrace
end
i.e., the on_message
method might look like this:
def on_message buffer
begin
length = buffer.length
pos = 0
while length >= @expecting
@msg << (buffer[pos, @expecting])
@out_file.puts(@msg.unpack('H*')[0])
length -= @expecting
pos += @expecting # the spelling mistake was here
@expecting = 86
@msg.clear
end
if(length > 0)
@msg << (buffer[pos, length])
@expecting = 86 - length
end
puts @msg unless @msg.empty? # print leftovers for testing...?
rescue => e
# oops something happened. React
puts e.message, e.backtrace
end
end
Also, FYI, iodine allows you to control the number of processes (workers) and threads you'r using. See the documentation for details.
来源:https://stackoverflow.com/questions/46199512/handle-avl-messages-with-iodine