Вопрос по c#, c++, visual-c++ – Двухсторонняя связь C ++ с C # с использованием именованных каналов

6

Я пытаюсь установить двустороннюю связь между приложением VC ++ 6 и приложением C #. Я использую именованные каналы. В моем коде C ++ я могу прочитать сообщение от клиента C #, но затем сервер «умирает», и я должен перезапустить его снова.

Что я хочу сделать, так это подключить приложение C # к приложению C ++, запросить состояние, и приложение C ++ выключится и проверит состояние, а затем вернет либо «занято», либо «бездействует».

Я не могу ничего написать обратно клиенту C #, так как он говорит, что соединение закрыто. Некоторые вещи, которые я прокомментировал, уже испробованы.

C ++ код (начался как поток)

UINT CNamedPipe::StartNamedPipeServer()
{
LPTSTR lpszPipename = "\\\\.\\pipe\\SAPipe"; 
    HANDLE hPipe; 
    BOOL flg;
    DWORD dwWrite,dwRead;
    char szServerUpdate[200];
    char szClientUpdate[200];

    hPipe = CreateNamedPipe (    lpszPipename, 
                                PIPE_ACCESS_DUPLEX,
                                PIPE_TYPE_MESSAGE | 
                                PIPE_READMODE_MESSAGE | 
                                PIPE_NOWAIT,                    //changed from nowait
                                PIPE_UNLIMITED_INSTANCES,    // max. instances 
                                BUFSIZE,                    // output buffer size 
                                BUFSIZE,                    // input buffer size 
                                PIPE_TIMEOUT,                // client time-out 
                                NULL);                        // no security attribute 

    if (hPipe == INVALID_HANDLE_VALUE) 
        return 0;

    ConnectNamedPipe(hPipe, NULL);

    while(m_bServerActive)  //This seems to work well ....
    {

        //Read from client
        flg = ReadFile(hPipe,szClientUpdate,strlen(szClientUpdate),&dwRead, NULL);

        if(flg) //Read something from the client!!!!
        {
            CString csMsg,csTmp;

            for(int i=0;i<dwRead;i++){
                csTmp.Format("%c",szClientUpdate[i]);
                csMsg += csTmp;
            }


            AfxMessageBox("Client message: " + csMsg);

            strcpy( szServerUpdate,"busy");

            //Write status to Client
            flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);

            EndServer();
            StartServer();
        }

    }

    return 0;

}

C # Код:

public void ThreadStartClient(object obj)
    {
        // Ensure that we only start the client after the server has created the pipe
        ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

        // Only continue after the server was created -- otherwise we just fail badly
        // SyncClientServer.WaitOne();

        using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
        {
            // The connect function will indefinately wait for the pipe to become available
            // If that is not acceptable specify a maximum waiting time (in ms)
            pipeStream.Connect();

            //Write from client to server
           using (StreamWriter sw = new StreamWriter(pipeStream))
            {
                sw.WriteLine("What's your status?");
           }

            //Read server reply
            /*using (StreamReader sr = new StreamReader(pipeStream))
            {
                string temp = "";
                temp = sr.ReadLine();   //Pipe is already closed here ... why?

                MessageBox.Show(temp);

            }*/

            //pipeStream.Close();

        }
    }
}

Ваш Ответ

2   ответа
10

StreamWriter илиStreamReader закроет основной поток.

Таким образом, использование операторов будет приводить к закрытию потока.

    public void ThreadStartClient(object obj)
    {
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

            // Only continue after the server was created -- otherwise we just fail badly
            // SyncClientServer.WaitOne();

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
            {
                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();


                //Write from client to server
                StreamWriter sw = new StreamWriter(pipeStream))
                sw.WriteLine("What's your status?");

                //Read server reply
                StreamReader sr = new StreamReader(pipeStream)
                string temp = "";
                temp = sr.ReadLine();   //Pipe is already closed here ... why?

                MessageBox.Show(temp);
            }
    }

Следует также отметить, что, поскольку вы заключаете свой поток в оператор использования, закомментированныйpipeStream.Close() функция не нужна.

Спасибо, это отличная помощь. Я изменю свой код и посмотрю, что произойдет. Как вы уже догадались, я новичок в C #. Bob Moore
Нет проблем, не забудьте нажать чек под голосами, чтобы получить лучший рейтинг одобрения! Blam
4

Вот сервер C ++ (запустите его внутри потока):

UINT CNamedPipe::StartNamedPipeServer()
{
    if(!m_bServerActive)
        return 0;

    LPTSTR lpszPipename = "\\\\.\\pipe\\MyPipe"; 
        HANDLE hPipe; 
        BOOL flg;
        DWORD dwWrite,dwRead;
        char szServerUpdate[200];
        char szClientUpdate[200];

        hPipe = CreateNamedPipe (    lpszPipename, 
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_MESSAGE | 
                                    PIPE_READMODE_MESSAGE | 
                                    PIPE_WAIT,                  //HAS TO BE THIS
                                    PIPE_UNLIMITED_INSTANCES,    // max. instances 
                                    BUFSIZE,                    // output buffer size 
                                    BUFSIZE,                    // input buffer size 
                                    PIPE_TIMEOUT,                // client time-out 
                                    NULL);                        // no security attribute 

        if (hPipe == INVALID_HANDLE_VALUE) 
            return 0;

        ConnectNamedPipe(hPipe, NULL);


        strcpy( szServerUpdate,"busy");

        //Write status to Client
        flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);

        EndServer();
        StartServer();

        return 0;
}

А вот клиент C #:

public void ThreadStartClient(object obj)
        {
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut))
            {

                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();

                if (!pipeStream.IsConnected)    //It thinks it's connected but can't read anything ....
                {
                    MessageBox.Show("Failed to connect ....");
                    return;
                }

                //Read server reply
                StreamReader sr = new StreamReader(pipeStream);

                char[] c = new char[200];

                while (sr.Peek() >= 0)
                {
                    sr.Read(c, 0, c.Length);
                }

                string s = new string(c);
                MessageBox.Show(s);
            }
        }

Я на самом деле ничего не отправляю с клиента на сервер, потому что мне не нужно ... ключевой момент в этом - параметр PIPE_WAIT в функции CreateNamedPipe (). Это заставляет сервер ждать подключения клиента.

Похожие вопросы