Вопрос по работе с портом под сервером-терминалов (Win2003)

Темы, которые не попадают в остальные категории.
Ответить
FireBoy
Сообщения: 8
Зарегистрирован: Пт ноя 28, 2008 1:06 pm

Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение FireBoy »

Предыстория:
Есть компьютер, который работает с оборудованием, подключенному к COM-порту. Есть программа, написанная на Delphi. Все работает нормально.
Далее была дана задача переместить на сервер терминалов (Win2003). При подключении к нему, ставлю галочку «Подключать последовательные порты». Подключился. Запускаю стандартную программу, которая поставлялась с оборудованием. Все работает. Запускаю свою программу – не работает.

А теперь вопрос:
При запуске программы есть функция открыть порт, все нормально. Далее при приеме данных ничего не выдает, будто не видит данные. Даже если данных нет, все равно что-то с порта берет (проверял локально).
Может при открытии порта нужно указывать дополнительные опции? Или при сервере с ОС Win2003, нужно как-то по-другому считывать данные с порта? Или может еще что-нибудь. Подскажите, пожалуйста.

Процедура открытия порта:


Код: Выделить всё

function OpenComm(Num : integer; var Com_Var : TComVar) : boolean;
var
  ThreadId : DWord;
  TimeOuts : TCommTimeouts;
begin
  Result := False;
  with Com_Var do begin
//получаем хэндл
    cId := CreateFile(PChar('\\.\COM' + IntToStr(Num)),
  		                GENERIC_READ or GENERIC_WRITE,
                      0,nil,OPEN_EXISTING,
			                FILE_FLAG_OVERLAPPED,0);
    if cId = INVALID_HANDLE_VALUE then Exit;
//устанавливаем маску эвентов
    if not (SetCommMask(cId,EV_RXCHAR or EV_DSR or EV_CTS) and
//устанавливаем длину буферов ввода-вывода драйвера
	    SetupComm(cId,512,512) and
//очищаем все и вся
 	    PurgeComm(cId,PURGE_TXABORT or PURGE_RXABORT or
		                PURGE_TXCLEAR or PURGE_RXCLEAR) and
//записываем DCB
	    SetCommState(cId,DCB))
     then begin
       CloseHandle(cId);
	     Exit;
     end;
//настраиваем таймауты на немедленный возврат из Read(Write)File
    TimeOuts.ReadIntervalTimeout := 50;
    TimeOuts.ReadTotalTimeoutMultiplier := 1;
    TimeOuts.ReadTotalTimeoutConstant := 300;
    TimeOuts.WriteTotalTimeoutMultiplier := 1;
    TimeOuts.WriteTotalTimeoutConstant := 300;
//записываем таймауты
    SetCommTimeouts(cId,TimeOuts);
//опускаем флаг завершения дочернего потока
    Terminated := False;
//стартуем дочерний поток, функция потока - WorkComm
    CommThread := CreateThread(nil,0,@WorkComm,@Com_Var,0,ThreadID);
    if CommThread = 0 then begin
      CloseHandle(cId);
      Exit;
    end;
//устанавливаем приоритет дочернего потока
    SetThreadPriority(CommThread,8);
    Result := True;
  end;
end;
[/size]


Процедура работы с портом:

Код: Выделить всё

function WorkComm(var Parms : TComVar) : longint; stdcall;
var
  Kols, Mask,Trans,Errs : DWord;
  Ovr : TOverlapped;
  Buff : array [0..255] of byte;
  Reciv : pointer;
begin
  Result := 0;
//инициализируем TOverlapped структуру
  FillChar(Ovr,SizeOf(TOverlapped),0);
  Ovr.hEvent := CreateEvent(nil,TRUE,FALSE,#0);
//стартуем бесконечный цикл
  while not Parms.Terminated do with Parms do begin
    if Terminated then break;
    Mask := 0;
//запрашиваем (ожидаем) маску эвентов
    if not WaitCommEvent(cId,Mask,@Ovr) then begin
    //обрабатываем "отложенную" операцию ввода-вывода
    //не задумывался о ее смысле, просто откуда то содрал
      if GetLastError() = ERROR_IO_PENDING
       then GetOverlappedResult(cId,Ovr,Trans,True);
    end;
//очищаем ошибки с получением статуса порта, обязательно!!!
    ClearCommError(cId,Errs,@Stat);
    if Terminated then break;
    if Mask = 0  then continue;
    if (Mask and EV_RXCHAR) = EV_RXCHAR then begin
    //если принят хотя бы один байт
	    if Stat.cbInQue < 512
	     then Kols := Stat.cbInQue
       else Kols := 512;
      if Terminated then break;
    //пытаемся читать принятые байты
      ReadFile(cId,Buff,Kols,Kols,@Ovr);
      if Terminated then break;
   //////////////////////// в данном месте Kols = 0.
      if Kols > 0 then begin
      //если хоть один байт считан - переносим в буфер накопления
        GetMem(Reciv,kols);
        Move(Buff,Reciv^,kols);
        //шлем сообщение основному потоку
        PostMessage(fmMain.Handle,cmRxByte,integer(Reciv),kols);
      end;
    end;
  end;
  CloseHandle(Ovr.hEvent);
end;
[/size]
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

Вроде бы правильно.

Дай мне это откомпилированное на aka@pxe.ru, поищу где оно затыкается.
FireBoy
Сообщения: 8
Зарегистрирован: Пт ноя 28, 2008 1:06 pm

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение FireBoy »

Вряд ли получится запустить и просмотреть, т.к. используется не стандартное оборудование. Поэтому и данные посылаются специфичные.
Хотелось бы узнать, может для сервера терминалов функция открытия или считывания как-то по-другому прописывается. Либо нужно добавить пару функций или процедур.
Просто есть похожая ситуация. Тоже самое делается в другом городе, т.е. не делается, а нужно сделать. Со стандартной программой в самом начале идет долгая инициализация где-то 7 секунд. И в там так же не работает написанный драйвер.

Но откомпилированный файл шлю... Может получится ;-)
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

Эта. Про нестандартное оборудование.

А можешь отломать от всей программы только кусок, который читает порт вот этим самым способом, и просто кидать на экран все что из порта приходит? Железка, которая просто отдает данные, у нас найдется. Она любит работать с "наиболее стандартными" настройками, т.е. 9800, 8-N-1.
KVIK
Сообщения: 402
Зарегистрирован: Сб июн 17, 2006 5:45 pm
Откуда: Украина, Черновцы
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение KVIK »

aka писал(а):.... 9800, 8-N-1.
9600?
у нас при программировании самое больное место в компортах втваре это существенная задержка для набора целого пакета (там что-то порядка 1500 байт) при отправке по тсп/ип, некоторое железо этого не понимает и желает получат данные без перерыва.
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

KVIK писал(а):9600?
Да, точно. 9600, 8-N-1.
KVIK писал(а):задержка для набора целого пакета (там что-то порядка 1500 байт) при отправке по тсп/ип, некоторое железо этого не понимает и желает получат данные без перерыва.
The Nagle algorithm. Отключается галкой сокета TCP_NODELAY. У втвари всегда отключено, т.е. втварь не ждет заполнения, а сразу отправляет маленькие кусочки. Неужели у виндовса включено?
KVIK
Сообщения: 402
Зарегистрирован: Сб июн 17, 2006 5:45 pm
Откуда: Украина, Черновцы
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение KVIK »

aka писал(а):The Nagle algorithm. Отключается галкой сокета TCP_NODELAY. У втвари всегда отключено, т.е. втварь не ждет заполнения, а сразу отправляет маленькие кусочки. Неужели у виндовса включено?
ну не знаю, но как-то пробовали подключать фискальные регистраторы, пакет идет рывками, аппарат не понимал, повторами пакетов конечно лечилось, но тормознуто все было. немного потыкались и отказались от втваре на посах (там не только это, были ещё ряд небольших проблем, поэтому решили что проще хп юзать). возможно лагает и при отправлении сразу, когда команда попадает в разные пакеты разрыв тоже будет и тупому аппарату это не нравится. помню лет 15 назад делал нечто подобное на ско юниксе (терминал через компорт) была та же проблема, пришлось в самой проге терминала анализировать команду для аппарата и посылать её целиком, а не тупо прокидывать во второй компорт. :D
но процентов 80 устройств работают в втваре без всяких проблем :mrgreen:
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

KVIK писал(а):пакет идет рывками
Есть такая проблема. Это точно не Nagle, потому как отключен. Я подозреваю, что виндовс как раз ждет какое-то время, чтобы обеспечить плавность передачи. Надо рыть глубже...
FireBoy
Сообщения: 8
Зарегистрирован: Пт ноя 28, 2008 1:06 pm

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение FireBoy »

Я, конечно, не очень смыслю в протоколах и как Винда работает с ними.
Но один факт я знаю точно, что программа, которая пришла к нам вместе с оборудованием - работает прекрасно через сервер-терминалов. Они как-то прописали работу с портом, несмотря на то, что порт не локальный.
Значит есть почти стандартный алгоритм, который и локально нормально работает и через терминал с подключенным портом.
FireBoy
Сообщения: 8
Зарегистрирован: Пт ноя 28, 2008 1:06 pm

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение FireBoy »

Здравствуйте.
Хотел бы возвратиться к данному вопросу. Как переделать код программы, чтобы Винда в терминале нормально общалась с СОМ портом, т.к. проблема всё еще не разрешилась. Если кто-то что-то нашел, буду очень признателен за подсказку или верное решение.
За ранее, большое спасибо...

********************
* Удачи и добра всем!!! *
********************
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

В одну кучу смешаны waitonmask, overlapped io и таймауты read/write. Любой из этих методов работает, когда он один. Использовать все три одновременно не надо, получается каша.

А самое смешное, что ты же все равно ждешь бесконечным циклом в отдельном потоке. Т.е. все эти умные вещи тебе не нужны. Тебе нужен просто блокирующий ReadFile. Выкинь лишнее и будет тебе счастье.
FireBoy
Сообщения: 8
Зарегистрирован: Пт ноя 28, 2008 1:06 pm

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение FireBoy »

Эт получается просто закоментить этот блок?

Код: Выделить всё

//запрашиваем (ожидаем) маску эвентов
    if not WaitCommEvent(cId,Mask,@Ovr) then begin
    //обрабатываем "отложенную" операцию ввода-вывода
    //не задумывался о ее смысле, просто откуда то содрал
      if GetLastError() = ERROR_IO_PENDING
       then GetOverlappedResult(cId,Ovr,Trans,True);
    end;
И будет мне счастье? :)
aka
Разработчик
Разработчик
Сообщения: 11806
Зарегистрирован: Ср окт 01, 2003 12:06 am
Откуда: Роcсия, Тольятти
Контактная информация:

Re: Вопрос по работе с портом под сервером-терминалов (Win2003)

Сообщение aka »

FILE_FLAG_OVERLAPPED, SetCommMask, SetupComm, PurgeComm, SetCommTimeouts, SetThreadPriority, CreateEvent, WaitCommEvent, GetOverlappedResult - это все лишнее.

Надо делать CreateFile, CreateThread, ReadFile. ВСЕ. Все остальное будешь использовать, когда поймешь, как оно работает.
Ответить

Вернуться в «Остальное»