C++ 和 Java 应用程序之间的 NamedPipe 交互进程
NamedPipe interprocess between c++ and Java application
我需要从 C++ 端启动命名管道服务器并获取 java 应用程序以从管道读取。
对于创建管道的 C++ 端,我遵循了 MSDN 中的示例:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx
从Java结束,我做了一段hacky代码来测试:
Thread readerThread = new Thread( new Runnable()
{
@Override
public void run()
{
String line = null;
while( true )
{
try
{
final RandomAccessFile pipe =
new RandomAccessFile( "\\\\.\\pipe\\smarts_interprocess", "r" );
while( null != ( line = pipe.readLine() ) )
{
s_logger.warning( line );
}
}
catch( IOException ex )
{
s_logger.severe( ex.getMessage() );
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
s_logger.info( "nothing available, I will sleep for a second" );
}
}
}
}
} );
readerThread.start();
C++ 端代码:
void Pipe::startMessageLoop()
{
DWORD dwWait{};
BOOL fSuccess;
fPendingIO = ConnectToNewClient(m_inputHandle, &oOverlap_);
while (true)
{
dwWait = ::WaitForSingleObject(oOverlap_.hEvent, INFINITE);
if (dwWait == WAIT_FAILED)
{
::CloseHandle(oOverlap_.hEvent);
std::cout << "failed to WaitForSingleObject.." << std::endl;
}
if (fPendingIO)
{
DWORD cbRet;
fSuccess = GetOverlappedResult(
m_inputHandle, // handle to pipe
&oOverlap_, // OVERLAPPED structure
&cbRet, // bytes transferred
FALSE); // do not wait
switch (dwState)
{
// Pending connect operation
case CONNECTING_STATE:
if (!fSuccess)
{
printf("Error %d.\n", GetLastError());
return;
}
dwState = WRITING_STATE;
break;
// Pending write operation
case WRITING_STATE:
if (!fSuccess)
{
DisconnectAndReconnect();
continue;
}
break;
default:
{
printf("Invalid pipe state.\n");
return;
}
}
}
std::string message = "naive message from server";
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring data = converter.from_bytes(message.c_str());
DWORD numBytesWritten = 0;
switch (dwState)
{
case WRITING_STATE:
fSuccess = WriteFile(
m_inputHandle, // handle to our outbound pipe
data.c_str(), // data to send
wcslen(data.c_str()) * sizeof(wchar_t), // length of data to send (bytes)
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);
// FlushFileBuffers(m_inputHandle);
// The write operation completed successfully.
if (fSuccess)
{
fPendingIO = FALSE;
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
dwState = WRITING_STATE;
continue;
}
// The write operation is still pending.
if (!fSuccess && (GetLastError() == ERROR_IO_PENDING))
{
fPendingIO = TRUE;
continue;
}
// An error occurred; disconnect from the client.
DisconnectAndReconnect();
break;
default:
{
printf("Invalid pipe state.\n");
return;
}
}
}
}
它可以毫无问题地连接到管道,但唯一的问题是 java end 在 C++ 进程完成(从 VS 终止调试器)之前无法获取写在 c++ 端的数据我是说)。
只要我的 C++ 进程还在 运行,它就挂在 readLine 的点上:
行 = pipe.readLine()
有人对此有任何想法吗?
据我所知 - 如果您在服务器端使用了完全相同的 MSDN 代码 - 服务器在将任何内容写入管道之前正在等待输入。如果您的客户端从不发送任何内容,那么 pipe.readLine
将阻塞直到连接被切断。
Java 不是我的菜,但我猜服务器的响应还必须包含 readLine
到 return.[=12= 的换行符]
如果您在 readLine()
中被阻止,对方不会发送线路。它在对等方退出时解除阻塞的原因是 reader 遇到流的结尾,并且 returns 目前收到的数据。
您需要找出对端正在发送的内容并使用合适的读取方法。显然它不是线条,所以 readLine()
是错误的工具。
我需要从 C++ 端启动命名管道服务器并获取 java 应用程序以从管道读取。
对于创建管道的 C++ 端,我遵循了 MSDN 中的示例: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx
从Java结束,我做了一段hacky代码来测试:
Thread readerThread = new Thread( new Runnable()
{
@Override
public void run()
{
String line = null;
while( true )
{
try
{
final RandomAccessFile pipe =
new RandomAccessFile( "\\\\.\\pipe\\smarts_interprocess", "r" );
while( null != ( line = pipe.readLine() ) )
{
s_logger.warning( line );
}
}
catch( IOException ex )
{
s_logger.severe( ex.getMessage() );
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
s_logger.info( "nothing available, I will sleep for a second" );
}
}
}
}
} );
readerThread.start();
C++ 端代码:
void Pipe::startMessageLoop()
{
DWORD dwWait{};
BOOL fSuccess;
fPendingIO = ConnectToNewClient(m_inputHandle, &oOverlap_);
while (true)
{
dwWait = ::WaitForSingleObject(oOverlap_.hEvent, INFINITE);
if (dwWait == WAIT_FAILED)
{
::CloseHandle(oOverlap_.hEvent);
std::cout << "failed to WaitForSingleObject.." << std::endl;
}
if (fPendingIO)
{
DWORD cbRet;
fSuccess = GetOverlappedResult(
m_inputHandle, // handle to pipe
&oOverlap_, // OVERLAPPED structure
&cbRet, // bytes transferred
FALSE); // do not wait
switch (dwState)
{
// Pending connect operation
case CONNECTING_STATE:
if (!fSuccess)
{
printf("Error %d.\n", GetLastError());
return;
}
dwState = WRITING_STATE;
break;
// Pending write operation
case WRITING_STATE:
if (!fSuccess)
{
DisconnectAndReconnect();
continue;
}
break;
default:
{
printf("Invalid pipe state.\n");
return;
}
}
}
std::string message = "naive message from server";
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring data = converter.from_bytes(message.c_str());
DWORD numBytesWritten = 0;
switch (dwState)
{
case WRITING_STATE:
fSuccess = WriteFile(
m_inputHandle, // handle to our outbound pipe
data.c_str(), // data to send
wcslen(data.c_str()) * sizeof(wchar_t), // length of data to send (bytes)
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);
// FlushFileBuffers(m_inputHandle);
// The write operation completed successfully.
if (fSuccess)
{
fPendingIO = FALSE;
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
dwState = WRITING_STATE;
continue;
}
// The write operation is still pending.
if (!fSuccess && (GetLastError() == ERROR_IO_PENDING))
{
fPendingIO = TRUE;
continue;
}
// An error occurred; disconnect from the client.
DisconnectAndReconnect();
break;
default:
{
printf("Invalid pipe state.\n");
return;
}
}
}
}
它可以毫无问题地连接到管道,但唯一的问题是 java end 在 C++ 进程完成(从 VS 终止调试器)之前无法获取写在 c++ 端的数据我是说)。
只要我的 C++ 进程还在 运行,它就挂在 readLine 的点上: 行 = pipe.readLine()
有人对此有任何想法吗?
据我所知 - 如果您在服务器端使用了完全相同的 MSDN 代码 - 服务器在将任何内容写入管道之前正在等待输入。如果您的客户端从不发送任何内容,那么 pipe.readLine
将阻塞直到连接被切断。
Java 不是我的菜,但我猜服务器的响应还必须包含 readLine
到 return.[=12= 的换行符]
如果您在 readLine()
中被阻止,对方不会发送线路。它在对等方退出时解除阻塞的原因是 reader 遇到流的结尾,并且 returns 目前收到的数据。
您需要找出对端正在发送的内容并使用合适的读取方法。显然它不是线条,所以 readLine()
是错误的工具。