Avatar billede skov_p Praktikant
22. april 2008 - 10:39 Der er 8 kommentarer og
1 løsning

Async TCP mangler svar fra server

Hej

Jeg har lavet en klasse der kommunikerer men en host via. async TCP kald.
Det virker ok bortset fra hvis der feks. skal tastes noget på hosten får jeg ikke svar før end at jeg sender noget nyt til hosten.

Feks.
Client <-> Host
Hvad er klokken ->
<- 10:55
Tast et 123 og tryk enter->
//Nu kommer der ikke noget når trykkes enter
Hvad er klokken ->
<- 123
<- 11:15

Svaret på "Tast et 123 og tryk enter" kommer altså først på min næste forespørsel.

Jeg kan løse det en BeginReceive i min ReceiveData
void ReceiveData(IAsyncResult iar) {
      try {
        StateObject so = (StateObject)iar.AsyncState;
        int recv = so.WorkSocket.EndReceive( iar );
        List<byte> rec = new List<byte>( so.Data );
        OnDataReceived( rec.GetRange( 0, recv ).ToArray() );
        so.WorkSocket.BeginReceive( so.Data, 0, so.Data.Length, SocketFlags.None, new AsyncCallback( ReceiveData ), so );
      } catch( Exception ex ) {
        OnError( "ReceiveData error:" + ex.Message );
      }
    }

Men hvis der udføres et kald der ikke skal returnerer noget får jeg lagt en BeginReceive i "kø".
Vil det ikke give mig et problem på sigt
Avatar billede nielle Nybegynder
22. april 2008 - 12:33 #1
Hvorfor ikke bare returnere noget ved hvert kald? F.eks. "ok" eller "ack". Så er du også mere sikker på at serveren ikke er gået i baglås over et eller andet i input.
Avatar billede skov_p Praktikant
22. april 2008 - 14:20 #2
Det er ikke mig der laver hosten.
Det er et stykke ældre SW i en printer der ikke kan ændres på.
Avatar billede skov_p Praktikant
22. april 2008 - 14:24 #3
Jeg vil også lige tilføje at det virker med Hyper Terminal så det er noget i min kode der fejler.
Hvis det ikke er noget problem at lave en BeginReceive i hver receive vedr. memory eller performance er det fint med mig. Men det kan jeg ikke gennemskue.
Avatar billede nielle Nybegynder
22. april 2008 - 17:50 #4
Ok, men hvis du kender protokollen, så skal du jo bare lade være med at kalde BeginRecive i de tilfælde hvor du ikke forventer et svar.
Avatar billede skov_p Praktikant
22. april 2008 - 18:46 #5
Jeg er mere interesseret i at vide hvordan jeg koder mig ud af det i stedet for at låse mig til denne specifikke printer.

Jeg fandt følgende på MSDN, her benyttes BeginReceive rekusivt.

http://msdn2.microsoft.com/en-us/library/bew39x2a.aspx

private static void ReceiveCallback( IAsyncResult ar ) {
        try {
            // Retrieve the state object and the client socket
            // from the asynchronous state object.
            StateObject state = (StateObject) ar.AsyncState;
            Socket client = state.workSocket;

            // Read data from the remote device.
            int bytesRead = client.EndReceive(ar);

            if (bytesRead > 0) {
                // There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));

                // Get the rest of the data.
                client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
                    new AsyncCallback(ReceiveCallback), state);
            } else {
                // All the data has arrived; put it in response.
                if (state.sb.Length > 1) {
                    response = state.sb.ToString();
                }
                // Signal that all bytes have been received.
                receiveDone.Set();
            }
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }


Men det jeg kommer aldrig til "else" delen, dvs. at det er det samme som i mit indledende spm.
Avatar billede nielle Nybegynder
22. april 2008 - 19:12 #6
Din kode skal under alle omstændigheder kende den protokol den skal kunne kommunikere via. Dette har ikke noget med at være bundet til en specifik printer, men derimod med at være bundet til en specifik protokol. Det ligger i protokollen at der er fast defineret hvornår der skal forventes et svar og hvornår der ikke gøres, og det er det dit program skal opføre sig efter.
Avatar billede skov_p Praktikant
22. april 2008 - 19:18 #7
Ok, men Hyper Terminal kender 100% ikke noget til protokollen og den er i stand til at modtage svaret trods det er "forsinket" af en evt. operation på hosten.

Med en rekusiv BeginReceive kommer alle de "bufferede" BeginReceive hvis forbindelsen afbrydes. Så de ligger altså og venter i al evighed. Ikke nogen god løsning.
Avatar billede skov_p Praktikant
22. april 2008 - 21:19 #8
I min oprindelige løsning startede jeg en BeginReceive på en EndSend da jeg forventer et svar fra hosten.
En løsning kunne være et flag der fortæller om den rekusive BeginReceive er startet og derefter unlade at starte en BeginReceive på en EndSend.
Så er der altid kun 1 BeginReceive der venter.
Jeg kan se at memory forbruget ikke stiger dramatisk som i løsningen i mit indledende spm.

Jeg lader lige tråden stå åben lidt tid endnu for evt. forslag.
Avatar billede skov_p Praktikant
24. april 2008 - 15:07 #9
Lukker
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester