简体   繁体   English

C ++和Java应用程序之间的NamedPipe进程间

[英]NamedPipe interprocess between c++ and Java application

I need start a named pipe server from c++ side and get a java application to read from the pipe. 我需要从c ++端启动一个命名管道服务器,并获取一个Java应用程序以从管道读取数据。

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 对于创建管道的C ++端,我遵循了MSDN上的示例: https : //msdn.microsoft.com/zh-cn/library/windows/desktop/aa365603(v= vs.85) .aspx

From Java end, I did a piece of hacky code to test: 从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++ side code: 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;
            }
        }
    }
}

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). 它可以连接到管道,没有任何问题,但是唯一的问题是,在C ++进程完成之前,Java端无法获取在c ++端上编写的数据(终止VS的调试程序是我的意思)。

As long as my C++ process still running, it hangs at the point to readLine: line = pipe.readLine() 只要我的C ++进程仍在运行,它就会挂在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. 据我所知-如果您在服务器端使用了完全相同的MSDN代码-服务器在将任何内容写入管道之前都在等待输入。 If your client never sends anything then pipe.readLine will block until the connection is severed. 如果您的客户端从不发送任何内容,则pipe.readLine将阻塞,直到断开连接为止。

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. Java不是我的事,但我猜测服务器的响应还必须包含换行符,以便readLine返回。

If you're blocked in readLine() , the peer isn't sending lines. 如果您在readLine()被阻止,则对等方不会发送行。 The reason it unblocks when the peer exits is that the reader encounters end of stream, and returns the data received so far. 当对等方退出时,其解除阻塞的原因是读取器遇到流的末尾,并返回到目前为止接收到的数据。

You need to find out what the peer is sending and use suitable read methods for it. 您需要找出对等方正在发送的内容,并使用适当的读取方法。 Clearly it isn't lines, so readLine() is the wrong tool for the job. 显然,这不是行,因此readLine()是完成此工作的错误工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM