This is a message copy from the iprog [
1] forum:
Автор: Alexey Rakov Дата: 16.04.10 18:29
Накатал такой тест на tcl (считается относительно медленным скриптовым языком).
Погонял с тестовым modbus-tcp slave'ом. Довольно резво все выходит - больше 500 запросов в секунду, период получается меньше 2 мс. Мастер: Pentium 4 1800МГц, подчиненный вообще нетбук с атомом, сеть: какой-то нонейм хаб.
Leks, обратите внимание, после посылки запроса, сразу же, без всяких пауз, идет чтение данных. Сокет сконфигурирован для работы в асинхронном режиме, если этого не сделать, чтение будет блокировать работу программы, и если данных не будет, прога зависнет. По любой ошибке сразу выход (это всего лишь тест :).
Ну и конечно, полученные результаты мало о чем говорят, реальный контроллер может гораздо медленнее отвечать.
На WinSockAPI в С или Делфи для ожидания данных с таймаутом лучше использовать select() с выставленным таймаутом, либо устанавливать обработчики сетевых событий и таймеров.
# простой модбас запрос, чтение адресов 400001-400010
set query [binary format H* 0000000601030000000A]
# устанавливаем соеденение с подчиненным устройством
set connection [socket 192.168.3.241 502]
fconfigure $connection -blocking 0 -buffering none -translation binary
set perftime [clock milliseconds]
set perfcnt 0
set transact_id 0
# цикл опроса
while {on} {
# формируем первые два байта заголовка и посылаем запрос
puts -nonewline $connection "[binary format S $transact_id]$query"
set response {}
set resplen 29 ;# длина ответа должна быть 29 байт !
set begtime [clock milliseconds]
# ждем ответа
while {$resplen} {
if { [eof $connection] } {
# соеденение закрыли на той стороне
puts "connection closed"
exit
}
# читаем прешедшие данные
if { [catch {read $connection $resplen} data] } {
# другая ошибка сокетов
puts $errorInfo
exit
} elseif { [string length $data] } {
# какие-то данные пришли
# добавляем, то что пришло к ответу
append response $data
# вычисляем, сколько еще осталось прочитать
incr resplen -[string length $response]
} else {
# ничего не пришло, проверка на таймаут
if { [clock milliseconds] - $begtime >= 300 } {
puts "connection timeout"
exit
}
}
}
# вычисляем идентификатор транзакции
binary scan $response S resp_id
set resp_id [expr {$resp_id & 0xFFFF}]
# проверям соответствие идентификаторов запроса и ответа
if {$transact_id != $resp_id} {
puts "modbus error"
exit
}
# раз в 10 секунд смотрим, сколько транзакций прошло
# вычисляем производительность и выводим на печать
incr perfcnt
if { [clock milliseconds] - $perftime >= 10000 } {
set queryinsec [format %.2f [expr {$perfcnt / 10.0}]]
set period [format %.4f [expr {10.0 / $perfcnt}]]
puts "perfomance: $queryinsec queries in sec, period: $period"
set perfcnt 0
set perftime [clock milliseconds]
}
}