Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.12.2011, 16:24   #1
clopcad
 
Регистрация: 23.11.2011
Сообщений: 5
По умолчанию Реализация протоколов в приложении

Написал класс для работы с ком портом (часть класса представлена ниже). Выложил не весь класс, при необходимости выложу весь.

это мой первый опыт работы с портами и протоколами (сетевым программированием) и проблема скорее всего связанна с непониманием некоторых принципов работы.

в классе я создаю поток TReadThread событие прихода байта перехватываю в классе с помощью OnReadByte

Код:

//поток для чтения последовательности байтов из COM-порта в буфер
class TReadThread : public TThread
{
 private:
       class TComPort *FOwner;
       byte FByte;
       COMSTAT FPState;
       DWORD FMState;
       DWORD FErrCode;
        void __fastcall DoReadByte();
 protected:
        void __fastcall Execute();	//основная функция потока
 public:
        __fastcall TReadThread(TComPort *AOwner);	//конструктор потока
};

typedef void (__closure *TReadByteEvent)(const byte B,COMSTAT PortStat,DWORD ErrCode,DWORD ModemState);


class TComPort
{

private:
    int FComNumber;                        //
    bool GetConnected();                   //
    void SetConnected(const bool Value);   //
    void SetComNumber(const int Value);    //
    void SetBaudRate(const int Value);     //
    void SetByteSize(const int Value);     //
    void SetParity(const int Value);       //
    void SetStopbits(const int Value);     //
    void SetReadActive(const bool Value);  //
    bool GetReadActive();
protected:
    int FBaudRate;   // cкорость обмена (бод)
    int FByteSize;   //число бит в байте
    int FParity;     //четность
    int FStopbits;   // число стоп-бит
    TReadThread *FReadThread;  //читающий поток
    void  DoOpenPort(); //открытие порта
    void  DoClosePort(); //закрытие порта}
    void  ApplyComSettings(); //установка параметров порта}
public:
    HANDLE FHandle;  //дескриптор порта
    TReadByteEvent FOnReadByte; //событие "получение байта"
        //конструктор
        __fastcall TComPort();
        //деструктор
        __fastcall ~TComPort();

        //Открывает/закрывает порт
        void Open();
        void Close();

        //Возвращает True, если порт открыт}
        bool  Connect();
        bool WriteByte(const byte B);

    //Возвращает структуру состояния порта ComStat, а в
    //переменной CodeError возвращается текущий код ошибки
    COMSTAT GetState(DWORD CodeError);
    //Возвращает состояние модема}
    DWORD GetModemState();

        //Возвращает True, если порт открыт
        __property bool Connected = {read = GetConnected, write = SetConnected };
        //Номер порта. При изменении порт переоткрывается, если был открыт}
        __property int ComNumber = {read = FComNumber,write = SetComNumber };
        //Скорость обмена}
        __property int BaudRate = {read = FBaudRate, write = SetBaudRate};
        //Число бит в байте}
        __property int ByteSize = {read = FByteSize, write = SetByteSize};
        //Четность}
        __property int Parity = {read = FParity, write = SetParity};
        //Число стоп-бит}
        __property int Stopbits = { read = FStopbits, write = SetStopbits};
        //Активность чтения порта}
        __property bool ReadActive = {read = GetReadActive, write = SetReadActive};
        //Событие, вызываемое при получении байта}
        __property TReadByteEvent OnReadByte =  {read = FOnReadByte, write = FOnReadByte};

};

__fastcall TComPort::TComPort()
{
FHandle = INVALID_HANDLE_VALUE;
FReadThread = NULL;
}

__fastcall TComPort::~TComPort()
{
DoClosePort();
}

void TComPort::Open()
{
 DoOpenPort();
}

void TComPort::Close()
{
 DoClosePort();
}


//открытие порта}
void TComPort::DoOpenPort()
{
char ComName[10];

 if (Connected) return;
 //Для портов 1..9 можно использовать простые имена COM1..COM9,}
 //но для портов 10-256 надо писать полное имя. Для общности   }
 //будем всегда использовать полное имя порта                  }
 sprintf(ComName,"\\\\.\\COM%d",FComNumber);

 //Открытие последовательного порта
 FHandle = CreateFile(
            ComName, //передаем имя открываемого порта}
            GENERIC_READ | GENERIC_WRITE, //ресурс для чтения и записи}
            0, // не разделяемый ресурс }
            NULL, // Нет атрибутов защиты }
            OPEN_EXISTING, //вернуть ошибку, если ресурс не существует}
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //асинхронный режим доступа}
            0 // Должно быть 0 для COM портов }
           ) ;
 //Если ошибка открытия порта - выход
 if (!Connected) return;
 //Инициализация порта}
 ApplyComSettings();

 FReadThread = new TReadThread(this);	//создать и запустить поток чтения байтов
 FReadThread->Resume();
}
clopcad вне форума Ответить с цитированием
Старый 11.12.2011, 16:24   #2
clopcad
 
Регистрация: 23.11.2011
Сообщений: 5
По умолчанию

Код:
//закрытие порта}
void TComPort::DoClosePort()
{
 if (!Connected) return;
 //Замораживаем поток чтения}
 ReadActive = false;
 //Уничтожение читающего потока
 FReadThread->FreeOnTerminate = true;
 FReadThread->Terminate();
 FReadThread = NULL;
 //Освобождение дескриптора порта}
 CloseHandle(FHandle);
 //Сброс дескриптора порта}
 FHandle = INVALID_HANDLE_VALUE;
}



bool TComPort::WriteByte(const byte B)
{
        DWORD Signaled, RealWrite, BytesTrans;
        OVERLAPPED WriteOL; //структура для асинхронной записи

        bool ret = false;

        //создание события для асинхронной записи}
        memset(&WriteOL,0,sizeof(WriteOL));
        WriteOL.hEvent = CreateEvent(NULL, true, true, NULL);

        try
        {
          //начало асинхронной записи}
          WriteFile(FHandle, &B, 1, &RealWrite, &WriteOL);
          //ожидания завершения асинхронной операции}
          Signaled = WaitForSingleObject(WriteOL.hEvent, INFINITE);
          //получение результата асинхронной операции}
          ret = ((Signaled == WAIT_OBJECT_0) &&
          (GetOverlappedResult(FHandle, &WriteOL, &BytesTrans, False)));
        }
        __finally
        {

          //освобождение дескриптора события}
          CloseHandle(WriteOL.hEvent);
        }

        return ret;
}



//конструктор потока ReadThread, по умолчанию пустой
__fastcall TReadThread::TReadThread(class TComPort *AOwner) : TThread(true)
{
  FOwner = AOwner;
}

//главная функция потока, реализует приём байтов из COM-порта
void __fastcall TReadThread::Execute()
{

    byte B;
    COMSTAT CurrentState;
    DWORD AvaibleBytes, ErrCode, ModemState, RealRead;
    OVERLAPPED ReadOL;
    DWORD Signaled, Mask;
    DWORD BytesTrans;


try{
    memset(&ReadOL,0,sizeof(ReadOL));
    ReadOL.hEvent = CreateEvent(NULL, true, true, NULL);

    SetCommMask(FOwner->FHandle, EV_RXCHAR);

    while ((!Terminated) && FOwner->Connected)
    {
     WaitCommEvent(FOwner->FHandle, &Mask, &ReadOL);
     Signaled = WaitForSingleObject(ReadOL.hEvent, INFINITE);
     if (Signaled  == WAIT_OBJECT_0)
      if (GetOverlappedResult(FOwner->FHandle, &ReadOL, &BytesTrans, false))
       if ((Mask & EV_RXCHAR) != 0)
       {

        CurrentState = FOwner->GetState(ErrCode);
        ModemState   = FOwner->GetModemState();

        AvaibleBytes = CurrentState.cbInQue;

        if (AvaibleBytes > 0)
         if (ReadFile(FOwner->FHandle, &B, 1, &RealRead, &ReadOL))
         {
          FByte   = B;
          FPState = CurrentState;
          FMState = ModemState;
          FErrCode= ErrCode;
          Synchronize(DoReadByte);

         }
       }
    }
}

  __finally {
   CloseHandle(ReadOL.hEvent);
   SetCommMask(FOwner->FHandle, 0);
   } 
}

//выводим принятые байты на экран и в файл (если включено)
void __fastcall TReadThread::DoReadByte()
{
 if (FOwner->OnReadByte) FOwner->FOnReadByte(FByte, FPState, FErrCode, FMState);
}

дальше в приложении перехватывал событие OnReadByte (заносит в Edit полученный байт и меняет свет Shape в зависимости от состояния порта). все работает хорошо. как бы класс отработал весь и вроде ни разу ошибок не было, мигают "лампочки" состояния порта и все такое.

дальше мне нужно реализовать протоколы более высокого уровня.
сначала протокол взаимодействия с устройством и потом протокол взаимодействия сети.

я хочу создать еще один класс TNewClass в котором будет использоваться объект типа TComPort
в этом классе буду перехватывать событие OnReadByte
и буду обрабатывать полученные байты согласно протокола взаимодействия с устройством и вынимать от туда информационную часть пакета, и после этого вызывать событие OnReadPaket в котором эта информационная часть будет обрабатываться и передаваться приложению.

собственно вопрос: не будут ли теряться принятые ком портом байты?
я думаю будут, т.к. (имхо) необходим какой-то механизм синхронизации.
если я прав, то посоветуйте решение этой проблемы или дайте ссылки на то, где почитать решение этой проблемы.
clopcad вне форума Ответить с цитированием
Старый 15.06.2012, 15:15   #3
IRA13-06
Новичок
Джуниор
 
Регистрация: 24.05.2010
Сообщений: 2
По умолчанию ComPort

Пришлите, пожалуйста полный код для работы с классом ComPort. Пытаюсь объявить этот класс в основном модуле:TComPort FPort; - при компиляции выдается ошибка.
Заранее спасибо.
IRA13-06 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Кнопка в приложении Nona Мультимедиа в Delphi 1 11.06.2010 22:47
Ассоциация протоколов... prizrak1390 Работа с сетью в Delphi 2 19.09.2009 22:47
Iframe в Приложении DanzI Общие вопросы Delphi 15 14.09.2009 16:29
Анализаторы сетевых протоколов TDrive Софт 2 04.09.2009 06:32
Программа для IPX/SPX/NetBios протоколов Alar Работа с сетью в Delphi 0 30.10.2006 14:05