I am using a main script in my tcl code in which i am opening a udp port to read the data coming on it. I have made this using fileevent for which i am entering into the event loop using “vwait” command. But i don’t want the main script to be blocked due to this. In short i want main script continuing in flow and the wait for udp data event should be in background. How to achieve this. Please help me. I have wasted a lot of time for this, but all in vein. Any help would be really appreciable.
Here is my main script :
#!/usr/bin/env tclsh8.5
proc create_udp_payload { command data } {
set payload ""
append payload $command
append payload [ format %08x [ expr $data ] ]
return $payload
}
proc send_udp_packet { payload } {
puts -nonewline $soc::s [binary format H* $payload]
puts "\nTransmitting the UDP payload $payload"
return 0
}
set DEST_IP_ADDR 10.10.20.241
set DEST_UDP_PORT 5558
set soc::s [udp_open]
puts "Listening on udp port : [fconfigure $soc::s -myport]"
udp_conf $soc::s $DEST_IP_ADDR $DEST_UDP_PORT
fconfigure $soc::s -buffering none -translation binary
fileevent $soc::s readable [list ::udp_listen]
for { set j 0 } { $j < 10 } { incr j} {
puts "Sending read request to read register $j"
set command "00"
append command [format %02x $j]
send_udp_packet [create_udp_payload $command 0x0000]
after 1000
flush $soc::s
}
wait forever #to enter into the event loop
for { set j 2 } { $j < 12 } { incr j} {
puts "Sending write request to write register $j"
set command "80"
append command [format %02x $j]
send_udp_packet [create_udp_payload $command [expr {0x0000 | $j }] ]
after 2000
flush $soc::s
}
Actually i want to read 10 registers one by one from a hardware, for which i am using a for loop, but i am not getting how to enter into event loop for this. Because it blocks the main script. Also after that i want to write 10 registers of the same hardware one by one. Can anybody please modify this code to work accordingly. Thanks in advance for that……..
I think your problem could be easily solved using the
after idle“trick”. The idea is to set up your “channel readable” event handlers, then schedule the execution of your data sending code for the “event loop is idle” condition, and then enter the event loop:Like this:
As soon as
vwaitis called, the event loop machinery sees if there’s any pending events (there should be none) and as soon as the queue of pending events is drained or is empty, all the handlers installed usingafter idleare called and your data is sent out.Note that this approach works for other similar cases as well, for instance, nothing prevents you from installing such
after idlehandlers from other handlers called by the event loop. This allows you to never ever leave the event loop (as GUI programs and network servers usually do).