这里的最终目标是让现有的 C++ 应用程序通过虚拟串行 COM 端口与现有的 C# 应用程序进行通信,这两者都是其他人编写的。我对串行通信不是很熟悉,上周左右我一直在研究它,但它仍然在我的脑海中,但这并没有让任务消失,所以我在这里。如果你能帮上忙,请记得到 ELI5。
在我完成这个任务的过程中,我最近的想法是从头开始编写一个 C++ 应用程序,它只是发送一个已知消息并接收一个预期的消息作为回报。我能够编写一个创建文件句柄的 C++ 应用程序,并使用 and 成功通过 COM 发送CreateFile(...)
消息WriteFile(...)
。我知道 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;
}
发件人将报告它按预期发送了消息。听者只是无限地重复'io pending'。
因此,任何一个问题的答案都会有所帮助:
- 为什么我的代码失败了?你如何使用 FILE_FLAG_OVERLAPPED?
- -或者-
- 一个应用程序发送/接收重叠,而另一个应用程序不重叠是否重要?
- 实际上第三个问题,为什么COM通信在一个方向上会成功,但在另一个方向上会失败?