c # — Связь через COM-порт ожидает навсегда с FILE_FLAG_OVERLAPPED на Win32

Конечная цель здесь — получить существующее приложение C ++ для связи через виртуальный последовательный COM-порт с существующим приложением C #, которое написал кто-то другой. Я не очень знаком с последовательными коммуникациями, я изучал их на прошлой неделе или около того, и это все еще далеко над моей головой, но это не делает задачу уйти, так что вот и я. Если вы можете помочь, пожалуйста, не забудьте ELI5.

В моей миссии по достижению этой цели моей последней идеей было написать приложение на C ++ с нуля, которое просто отправляло известное сообщение и получало ожидаемое сообщение взамен. Мне удалось написать приложение на C ++, которое создало дескриптор файла и успешно отправило сообщение через COM, используя CreateFile(...) а также WriteFile(...), Я знаю, что приложение C # получило сообщение, потому что оно сообщает о полученных данных правильно. Тем не менее, данные, отправляемые обратно из приложения C #, никогда не получаются моим ReadFile(...),

Следующим моим шагом было настроить мини-приложение на C ++ для отправки и прослушивания сообщений. Я обнаружил, что это работает, поэтому я знаю, что мое маленькое приложение может отправлять и получать сообщения через COM. Но приложение C # не может отправлять сообщения, поступающие на любой версия моих приложений на C ++.

Кто-то еще указал мне, что приложение C # использует FILE_FLAG_OVERLAPPED, тогда как все приложения C ++ используют FILE_ATTRIBUTE_NORMAL. Поэтому я начал пытаться настроить приложение C ++ на использование FILE_FLAG_OVERLAPPED, чтобы приложения C ++ и C # были согласованными. Однако это приводит к сбою приложения C ++, и я не могу понять, почему. Застрял на нем достаточно долго, чтобы попросить о помощи. Вот мой код, который завершается с ошибкой 997: ERROR_IO_PENDING и, кажется, никогда не получает сообщение (с перекрытием).

// ComTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"#include <cstdlib>
#include <iostream>
#include <Windows.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
cout << "hello, world" << endl;

HANDLE SerialHandle;

bool listener;
if (argc > 1) listener = true;
else listener = false;

if(listener) {
SerialHandle = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0);
} else {
SerialHandle = CreateFile(L"COM6", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0);
}
OVERLAPPED overlapped_structure;
memset(&overlapped_structure, 0, sizeof(overlapped_structure));
overlapped_structure.Offset = 0;
overlapped_structure.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

if( SerialHandle == INVALID_HANDLE_VALUE ) {
if( GetLastError() == ERROR_FILE_NOT_FOUND ) {
cout << "Serial Port 1 does not exist." << endl;
return 1;
}
cout << "Invalid Handle Value due to error: " << GetLastError() << endl;
return 2;
}
else {
cout << "Successfully opened the file handle." << endl;
}

DCB dcbSerialParams = {0};

dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

if (!GetCommState(SerialHandle, &dcbSerialParams)) {
cout << "Error retrieving comm state." << endl;
return 3;
}
else {
cout << "Retrieved comm state." << endl;
}

dcbSerialParams.BaudRate = CBR_19200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;

if (!SetCommState(SerialHandle, &dcbSerialParams)) {
cout << "Error setting comm state." << endl;
return 4;
}
else {
cout << "Comm state set." << endl;
}

cout << "Setting up timeouts . . . " << endl;

COMMTIMEOUTS timeouts = {0};

timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier = 10;

if (!SetCommTimeouts(SerialHandle, &timeouts)) {
cout << "Error setting up comm timeouts." << endl;
return 5;
}
else {
cout << "Comm timeouts set up." << endl;
}

typedef unsigned char UInt8;
UInt8 InputBuffer[2000] = {0};
UInt8 val = 130;
UInt8 * intBuffer = &val;
DWORD BytesRead = 0;

if (listener) {
cout << "Trying to read in listen mode" << endl;
ReadFile(SerialHandle, InputBuffer, 2000, &BytesRead, &overlapped_structure);
while (GetLastError() == ERROR_IO_PENDING){
cout << "error: io still pending" << endl;
}
}
else {  // if sender
if (!WriteFile(SerialHandle, intBuffer, 9, NULL, &overlapped_structure)) {
cout << "Error writing content." << endl;
}
else {
cout << "Wrote content: " << (int)(*intBuffer) << endl;
}
}

CloseHandle(SerialHandle);

return 0;
}

Отправитель сообщит, что отправляет сообщение, как и ожидалось. Слушатель просто бесконечно повторяет «в ожидании».

Так что ответ на любой вопрос будет полезен:

  • Почему мой код не работает? Как вы используете FILE_FLAG_OVERLAPPED?
  • -ИЛИ ЖЕ-
  • Имеет ли значение, что одно приложение отправляет / получает перекрывающиеся данные, а другое — нет?
  • На самом деле третий вопрос, есть ли другие идеи, почему COM-коммуникация была бы успешной в одном направлении, но потерпела неудачу в другом?

-2

Решение

Ваша ошибка проверить возвращаемое значение ReadFile является ошибкой. Ваш цикл while (GetLastError () == ERROR_IO_PENDING) является ошибкой.

Цель перекрывающегося метода чтения — позволить вашему коду делать что-то еще, пока чтение завершается в драйвере. Если вам нечем заняться (например, читать другие COM-порты), не пытайтесь использовать перекрывающийся метод. Нет смысла использовать перекрывающееся чтение только потому, что писатель использует перекрывающиеся записи: два конца независимы.

1

Другие решения


По вопросам рекламы [email protected]