Стартовая страница › Форумы › Ошибки в работе › Ошибки Коммуникатора › Ошибка DrvCnlBasic
- В этой теме 64 ответа, 2 участника, последнее обновление 7 месяцев назад сделано
Mikhail.
-
АвторСообщения
-
27.06.2025 в 14:31 #39216
MikhailМодератор> Он должен был остаться в буфере и по окончании сессии очищен.
Если данные ещё не дошли, то и очищены быть не могут.> Я правильно понимаю, что в текущей реализации это проблема System.Net.Sockets.NetworkStream и не лечится ?
Дело не в текущей реализации. Так работает TCP.
1. При настройке решаем, сколько времени будем ждать ответа.
2. Если не дождались нормального ответа, то устанавливаем статус устройства в ошибку и данные очищаются из буфера. Но в буфер могли прийти ещё не все данные, которые отправило устройство. Можно на уровне драйвера попробовать в своём коде подождать подольше и только затем очистить буфер — если так будет лучше, можно в канале связи реализовать.
3. Если приходит мусор, то надёжнее будет переподключиться.27.06.2025 в 14:32 #39217
MikhailМодераторИз кода драйвера можно проверить, какой канал связи используется.
27.06.2025 в 15:37 #39226
manjey73Участник@mikhail я пытался всеми правдами и неправдами по примерам из интернет при такой ситуации вычитать буфер в никуда в коде DrvCnlBasic, чтобы на следующей сессии все началось с начала.
Никакого результата это не дало.
Вся надежда на вас :), у меня не получилось.Данные не могут не прийти, ведь обрыва связи на самом деле не было, я просто специально для имитации уменьшал timeout ожидание ответа, и это сразу дает такой результат. Соответственно подобный же результат будет при реальной задержки ответа.
вчера полдня убил на различные варианте по очистке буфера из интернетов.
28.06.2025 в 08:07 #39241
manjey73УчастникНекоторые варианты очистки буфера начинают ругаться на то, что нет поддержки такого кода в C# 7.3 ибо netstandard 2.0 а не скажем NET8.
И вообще, +- интернет предлагает похожие решения. Типа извините, NetworkStreem не предлагает вариант Flush, так как оно тут ничего не делает, и лучший способ это переоткрыть клиента.-
Ответ изменён 12 месяцев назад пользователем
manjey73.
30.06.2025 в 17:02 #39267
MikhailМодераторИдея очистки такая
if (Connection is TcpConnection tcpConn) { try { tcpConn.ClearNetStream(inBuf); // или даже лучше с ожиданием таймаута используйте tcpConn.ReadAvailable(...) // или просто tcpConn.Read(...) } catch() { // здесь вывод в лог } }Буфер свой заведите любой длины. Потребуется добавить зависимость на драйвер канала связи.
30.06.2025 в 17:06 #39270
MikhailМодераторДаже обычное чтение будет забирать данные из буфера — главное не выпасть из Session по исключению. Это, возможно, самый простой способ — вызывать Read.
30.06.2025 в 17:31 #39274
manjey73УчастникПотребуется добавить зависимость на драйвер канала связи.
Имеете ввиду добавить DrvCnlBasic в зависимость и тогда пробовать чистить буфер?
Вернее писать его в никуда так понимаю между запросами ?01.07.2025 в 16:52 #39290
MikhailМодераторЧтобы класс TcpConnection был виден, потребуется добавить зависимость на DrvCnlBasic в свой проект.
Попробуйте просто обычное чтение выполнить для очистки буфера, если обнаружено нарушение формата данных.01.07.2025 в 16:57 #39293
manjey73УчастникСпасибо, попробую. Как доберусь. А то тут за ModAlarm взялся для дальнейших переделок 🙂
10.07.2025 в 16:06 #39389
manjey73Участник2025-07-10 15:59:30 Сеанс связи с устройством [49] Mbus_SDM Отправка (5): 10 40 FD 3D 16 Отправка (9): 68 03 03 68 53 01 B1 05 16 Приём (4/4): 68 90 90 68 Приём (52/146): 08 01 72 ........ Ошибка: некорректная длина ответа! Получено за 1013 мс 2025-07-10 16:00:00 Сеанс связи с устройством [49] Mbus_SDM Отправка (5): 10 40 FD 3D 16 Отправка (9): 68 03 03 68 73 01 B1 25 16 Приём (4/4): 82 09 0A FD Приём (11/11): 3A 82 09 0A FD 3A 00 00 0A FD 3A Ошибка: некорректная длина ответа! Read 159 - Приём (159/1024): 00 00 0A FD ........ Получено за 1638 мсстер длинный набор буков. Но суть, если произошло дочитывание, то следующая сессия начинается с начала
Но почему-то не всегда происходит дочитка.
Код такойprivate void ClearTcpConnection() { if (Connection is TcpConnection tcpConn) { try { //tcpConn.ClearNetStream(buf_in); // или даже лучше с ожиданием таймаута используйте tcpConn.ReadAvailable(...) // или просто tcpConn.Read(...) Thread.Sleep(10); string log = ""; byte[] buffer = new byte[1024]; while (tcpConn.NetStream.DataAvailable) // && totalWait < 1000 { int read = tcpConn.Read(buffer, 0, buffer.Length, 1000, ProtocolFormat.Hex, out log); Log.WriteLine($"Read {read} - {log}" ); if (read == 0) break; // Соединение закрыто } readcnt = 0; // Не знаю, надо или нет обнулять? } catch (Exception ex) { // здесь вывод в лог throw new ScadaException((Locale.IsRussian ? "Ошибка при очистке потока данных: " : "Error clearing data stream: ") + ex.Message, ex); } } }пока на больше у меня тямы не хватило
10.07.2025 в 16:45 #39390
manjey73УчастникtcpConn.ReadAvailable читает кусками, потому что tcpConn.NetStream.DataAvailable становится false.
Как тут сделать цикл, чтобы прочесть даже есть оно false ? но не больше заложенного буфера ?
10.07.2025 в 17:54 #39391
manjey73Участникprivate void ClearTcpConnection(int bufLength) { if (Connection is TcpConnection tcpConn) { try { string log = ""; byte[] buffer = new byte[bufLength - readcnt]; int totalWait = 0; int totalRead = 0; while (totalRead < buffer.Length && totalWait < PollingOptions.Timeout) { int read = tcpConn.ReadAvailable(buffer, 0, buffer.Length, ProtocolFormat.Hex, out log); // Log.WriteLine($"Read {read} DataAvailable {tcpConn.NetStream.DataAvailable} \n{log}"); // TEST Thread.Sleep(50); totalWait += 50; totalRead += read; } } catch (Exception ex) { // здесь вывод в лог throw new ScadaException((Locale.IsRussian ? "Ошибка при очистке потока данных: " : "Error clearing data stream: ") + ex.Message, ex); } } }В общем сварганил такое вот, может поправите в чем. Передаю размер буфера (тут может не совсем правильно) и отнимаю потом уже принятое.
-
Ответ изменён 11 месяцев, 2 недели назад пользователем
manjey73.
10.07.2025 в 19:40 #39393
manjey73УчастникКосяк в том, что DataAvailable почему-то не всегда true.
Как будто в буфер данные поступают порциями, а не целиком, раз они поступили.
Как такое может быть?11.07.2025 в 14:12 #39406
MikhailМодераторtcpConn.ReadAvailable читает кусками, потому что tcpConn.NetStream.DataAvailable становится false.
Как будто в буфер данные поступают порциями, а не целиком, раз они поступили.Так и есть. Данные поступают порциями, скорее всего потому, что протокол TCP их разбивает на куски. Поэтому дочитку делать, наверное, придётся по таймауту, а не по наличию данных. То есть дочитываем 1 секунду, например. Что пришло позже — уже не считаем и буфер забьётся.
11.07.2025 в 14:36 #39407
manjey73УчастникПонятно. В случае, если можно посчитать сколько данных должно быть, можно по счетчику. В остальных случаях по сути второй таймаут.. Ну хотя бы между сессиями точно чистит, потому что ClearNetStream(inBuf) почему-то не очищает, хотя вроде должен бы.
-
Ответ изменён 12 месяцев назад пользователем
-
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.