Hvordan man arbejder med navngivne rør (C + + server, C # klient)

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at komme i gang med at arbejde med navngivne rør, da jeg skal bruge dem til et projekt af mine i fremtiden.


I øjeblikket har jeg en C + + server, der venter til en klient forbinder og sender over en testmeddelelse. Jeg fulgte stort set denne vejledning for at komme i gang. Den relevante kode er nedenfor: [9]


    #define MESSAGE L"TestMessage"

HANDLE hnamedPipe = INVALID\_HANDLE\_VALUE;

hnamedPipe = CreateNamedPipe(
    L"\\.\pipe\testpipe",
    PIPE\_ACCESS\_DUPLEX,
    PIPE\_TYPE\_MESSAGE|
    PIPE\_READMODE\_MESSAGE|
    PIPE\_WAIT,
    PIPE\_UNLIMITED\_INSTANCES,
    1024,
    1024,
    NMPWAIT\_USE\_DEFAULT\_WAIT,
    NULL);

if(hnamedPipe == INVALID\_HANDLE\_VALUE)
{
        cout << "Failed" << endl;
}

while(true)
{
    cout<< "Waiting for client"<< endl;

    if(!ConnectNamedPipe(hnamedPipe,NULL))
    {
        if(ERROR\_PIPE\_CONNECTED != GetLastError())
        {
        cout << "FAIL"<< endl;
        }
    }

    cout<<"Connected!"<<endl;

    //Send over the message
    wchar\_t chResponse[] = MESSAGE;
    DWORD cbResponse,cbWritten;
    cbResponse = sizeof(chResponse);

    if(!WriteFile(
    hnamedPipe,
    chResponse,
    cbResponse,
    &cbWritten,
    NULL))
    {
        wprintf(L"failiure w/err 0x\%08lx
",GetLastError);
    }
    cout<<"Sent bytes :)" << endl;
}


Klientkoden (C #) er under:


        using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
        {
            while (true)
            {
                Console.WriteLine("Connecting to server...");
                pipeClient.Connect();

                Console.WriteLine("Connected :)");
                Console.WriteLine(pipeClient.ReadByte());
                pipeClient.Close();
                Console.WriteLine("Closed");
            }

        }


I øjeblikket har jeg fået klienten til at oprette forbindelse til serveren, og den udskriver den første byte. Jeg vil gerne vide, hvordan man gør 2 ting:



  1. Læs hele beskeden - Jeg forsøgte at bruge StreamReader over pipClient for at læse meddelelsen, men det hænger på ReadLine () på ubestemt tid.

  2. Fortsæt sende meddelelser - Jeg vil have, at serveren skal sende besked efter besked til klienten, som vil læse dem i et ad gangen og udskrive dem. Jeg er lidt clueless om IPC, så jeg forsøgte først at gøre klienten afbrudt og genoprette forbindelse til serveren i den tidlige (sande) sløjfe, mens serveren i et stykke tid er ægte sløjfe, som i toppen altid venter på en ny klientforbindelse før sender en anden besked. Mit forsøg på dette er i koden ovenfor.



Enhver hjælp med dette ville være meget værdsat. Til sidst er målet at sende over billeder fra serveren til klienten. Klienten vil derefter udskrive dem ud på skærmen i realtid. Jeg ønskede at få dette til at fungere med enkle strengmeddelelser, før jeg prøvede billeddataene.


REDIGERE:


Til sidst vil jeg kunne sende en besked fra klienten til serveren, der angiver, at den vil have den nyeste billedramme, så sender serveren den nyeste ramme, som klienten derefter vil vise på skærmen. Så strømmen er:



  1. Klient -> Server: Indikator, at klienten ønsker den nyeste rammeinformation. (Noget simpelt, måske et usigneret int med værdien 1)

  2. Server -> Client: Seneste frame info. (640x480 billede gemt i et byte array med RGB byte værdier)

  3. Klient: Vis rammen på skærmen.


Bedste reference


ReadLine hænger, fordi det venter på en newline, som din testmeddelelse ikke inkluderer.


Hvis du vil have serveren til at sende beskeder, skal du blot sætte en loop rundt om WriteFile opkaldet. Du behøver ikke at forbinde mere end én gang. Ligeledes i klienten sættes løkken rundt ReadLine.


Hvis hver besked består af tekst afsluttet af en ny linje, så skal det være tilstrækkeligt, men hvis du virkelig vil have rørklienten til at arbejde i meddelelsestilstand, skal du ringe:


pipeClient.ReadMode = PipeTransmissionMode.Message;


Jeg tvivler imidlertid på, at dette vil virke godt sammen med en StreamReader. I stedet skal du læse enkeltbeskeder med pipeClient.Read.


Opdater


At besvare dit nye spørgsmål:


På serveren, når klienten har tilsluttet, indtastes en loop, hvor:



  • Serveren læser fra klienten. Dette vil blokeres, indtil klienten beder om en ramme.

  • Serveren sender en ramme.



På klienten, når den er tilsluttet til serveren, indtastes en sløjfe, hvor:



  • Klienten sender en meddelelse 'send venligst en ramme'.

  • Klienten læser fra serveren for at få rammen.

  • Klienten viser rammen.



Jeg ville ikke bruge et meddelelsesmodus-rør. Hvis rammerne er fikset i størrelse, så ved klienten, hvor meget data der skal læses fra serveren. Ellers føres rammen med en uint, der indeholder dens længde.