#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
цикле.