C (Последовательный обмен данными с использованием ) — Как я могу заранее узнать, сколько символов будет прочитано методом ReadFile ()

#c

#c

Вопрос:

ReadFile(hSerial, buffer, 25, amp; dwBytesRead, 0);

Привет, ppl

Мой вопрос в том, как мне узнать, сколько символов вернет моя инструкция ReadFile перед вызовом ReadFile?. Устройство, с которым я общаюсь, возвращает разные данные на основе того, что было отправлено. Что касается приведенного выше файла чтения, в том случае я знал, что возвращаемые данные будут иметь длину 25 символов, но что, если я не знаю ответа, как я могу заменить 25 переменной, которой будет достаточно для любого объема полученных данных.

В моем коде вы увидите, что у меня есть 2 инструкции Readfile, в обоих случаях я знал объем данных, которые я получу, чтобы я отправил фиксированное число, что произойдет, если я не знаю этого количества?

 #include "stdafx.h"
#include "windows.h"

BOOL SetCommDefaults(HANDLE hSerial);
void StripCRLFandPrint(char *command);

char buffer[1000];
HANDLE hSerial;
DWORD dwBytesRead = 0;
DWORD dwBytesWritten = 0;
char trash;

int main(int argc, char* argv[])
{
    hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0 , 0 , OPEN_EXISTING , 0 , 0);

    if (hSerial == INVALID_HANDLE_VALUE) return GetLastError();

    SetCommDefaults(hSerial);//Initializing the Device Control Block

    COMMTIMEOUTS timeouts={0};
    timeouts.ReadIntervalTimeout=50;
    timeouts.ReadTotalTimeoutConstant=50;
    timeouts.ReadTotalTimeoutMultiplier=10;
    timeouts.WriteTotalTimeoutConstant=50;
    timeouts.WriteTotalTimeoutMultiplier=10;

    char szRxChar[3];//varialble holds characters that will be sent
    szRxChar[0] = '?';
    DWORD y =0, z =0;
    char buf[327];// will hold the data received 

    memset(buf,0,327);//initializing the buf[]
    memset(buffer,0,10000);

    WriteFile( hSerial , amp;szRxChar , 1, amp;dwBytesWritten ,0);
    ReadFile( hSerial ,  buf , sizeof(buf), amp;dwBytesRead , 0);
    printf("Retrieving data...nn");

    //Displaying the buffer
    printf( "%s",buf);

    printf("nData Read: %in",dwBytesRead);
    printf("Enter an option:");
    scanf("%c%c",amp;szRxChar,amp;trash);//Reading the next command to be sent

    while(szRxChar[0] != '1')//Press one to exit
    {
        memset(buffer,0,10000);
        //StripCRLFandPrint(szRxChar);
        WriteFile( hSerial , amp;szRxChar, 1, amp;dwBytesWritten ,0);
        ReadFile( hSerial ,  buffer , 25, amp;dwBytesRead , 0);

        printf("%s",buffer);
        printf("nData Read: %in",dwBytesRead);
        printf("n");
        printf("Enter an Option:");
        scanf("%c%c",amp;szRxChar,amp;trash);
    }

    CloseHandle(hSerial);// Closing the handle

    return 0;
}
  

Ответ №1:

Вы не можете знать, что вы запрашиваете, потому что ни одно программное обеспечение не может делать прогнозы относительно поведения удаленного конца. По этой причине чтение должно происходить в другом потоке. В потоке чтения вы можете указать ReadFile считывать по одному байту за раз. Вы можете выбрать одновременное чтение большего количества байтов, но тогда вы рискуете получить полное сообщение от другой части и все равно не получить уведомление, потому что ReadFile заблокирован в ожидании дополнительных данных.

Может быть сложно создать потоковый код самостоятельно. Я рекомендую вам поискать библиотеку, которая уже обрабатывает это за вас.

Ответ №2:

Вы никогда не узнаете точно, что было отправлено, но вместо того, чтобы вводить 25 , используйте sizeof(buffer) вместо этого.

Имейте в виду, что ReadFile() это не идеально. У меня возникли проблемы на более медленном оборудовании, тогда как ReadFile() не всегда читается полное сообщение, отправляемое через COM-порт. Поэтому может быть полезно читать побайтно, хотя и медленнее, чтобы убедиться, что вы получаете все сообщение:

  int c;
 DWORD dwBytesRead = 0;

 if (!(pcState[readerPort] amp; PORT_OPEN)) {
    RecvIndex = 0;
    Sleep(1000);
    return;
 }
 ReadFile(hComm[readerPort], buff, 1, amp;dwBytesRead, NULL); // array of handles used here
 c = buff[0];


 if (dwBytesRead == 0) {  // possible end of transmission
    if (RecvTimer   > 3) {
        RecvTimer = 0;
        if (RecvIndex) {      // have receive some data prior
            keyBuf[RecvIndex] = 0;
            RecvIndex = 0;
            processBuffer(keyBuf);
            memset(keyBuf, 0, sizeof(keyBuf));      
        }
    }
} else {
    RecvTimer = 0;  //Restart timer
    if (RecvIndex == 0) { // first character
        memset(keyBuf, 0, sizeof(keyBuf));
        keyBuf[0] = (unsigned char)c;
        RecvIndex = 1;
     } else {        // get remaining characters
        if (RecvIndex < sizeof(keyBuf))     
            keyBuf[RecvIndex  ] = (unsigned char)c;
     }
}
  

в приведенном выше примере keyBuf является частной переменной класса, а приведенный выше код является частью функции, которая вызывается в while цикле.