I need start a named pipe server from c++ side and get a java application to read from the pipe.
For the C++ side which creates the pipe, I followed the example from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx
From Java end, I did a piece of hacky code to test:
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++ side code:
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;
}
}
}
}
It can be connected to the pipe without any issue, but the only problem is that java end cannot get the data which was written on the c++ end until the C++ process finishes (terminates the debugger from VS I meant).
As long as my C++ process still running, it hangs at the point to readLine: line = pipe.readLine()
Anyone has any idea on this?
From what I can tell - if you've used exactly the same MSDN code for your server side - the server is waiting for input before it writes anything to the pipe. If your client never sends anything then pipe.readLine
will block until the connection is severed.
Java isn't my thing but I'm guessing that the response from the server must also contain a newline on order for readLine
to return.