Toon posts:

[c] reading multiple lines from socket

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik momenteel bezig met het schrijven van een programma die een verbinding opent naar een mailserver. Op het moment dat de verbinding gelegd is wil ik daar informatie uit lezen. Indien ik daar byte voor byte uitlees totdat ik een line-feed tegenkom ('\n') en er is daadwerkelijk iets te lezen gaat het goed.

Bij de mailserver van Tiscali krijg je dan zoiets:
+OK Tiscali POP server (v.3.0.0) started
Na deze lijn verwacht de mailserver input.

Maar op het moment dat ik nog een lijn wil uitlezen gaat het fout, die lijn is er namelijk niet. Dan blockt ie op het lezen. Hoe weet je dat er niets meer te lezen is??
Bij een webclient is dat niet zo lastig, je schrijft de request en dan lees je uit totdat de read functie faalt, omdat de server de verbindig verbroken heeft.

Nu weet ik toevallig dat de mailserver van Tiscali maar één statuslijntje laat zien, maar als het er meer (en een variabel aantal) zijn, hoe lees ik ze dan uit zonder dat ik daarop blockt als er niets meer is.

Niet echt van toepassing maar ik programmeer in C onder linux (kernel 2.4).

edit:

Ik heb het even met telnet bekeken en die schijnt er niet zo'n moeite mee te hebben om meerdere regels uit te lezen en als die er niet meer zijn gewoon weer met een input-prompt te verschijnen.

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Zou je het stukje code kunnen posten waarmee je de regels uitleest?

Verwijderd

Is er geen functie om op te vragen hoeveel bytes je nog kunt lezen voordat de stream leeg is? Ik weet niet hoe dat onder linux werkt (sockets zijn nou eenmaal OS specific)...
Anders moet je een non-blocking read doen en met semaforen werken, je kan een openstaande read dan cancelen na een timeout periode...

Verwijderd

Verwijderd schreef op 31 augustus 2002 @ 16:15:
...
Maar op het moment dat ik nog een lijn wil uitlezen gaat het fout, die lijn is er namelijk niet. Dan blockt ie op het lezen. Hoe weet je dat er niets meer te lezen is??
Bij een webclient is dat niet zo lastig, je schrijft de request en dan lees je uit totdat de read functie faalt, omdat de server de verbindig verbroken heeft.
...
Je moet de socket non-blocking instellen

Zoek maar eens op O_NONBLOCK of check de manual page van fcntl.

Verwijderd

Topicstarter
Orphix schreef op 31 augustus 2002 @ 16:28:
Zou je het stukje code kunnen posten waarmee je de regels uitleest?
Deze functie lees een lijn totdat ie ascii 10 of 0 tegenkomt, of er een error plaatsvind, maar als er niets is blijft read gewoon gewoon hangen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ssize_t read_line(int fd, char *ptr, size_t max)
{
   char *rptr;
   size_t nread, tread;
  rptr = ptr;
  tread = 0;
  while (tread < max)
  {
    nread = read(fd, rptr, 1);
    if (nread < 0)
    {
      if (errno == EINTR)
        nread = 0;
      else
        return -1;
    }
    else if (!nread)
      break;
    tread += nread;
    if ((rptr[0] == 10) || (!rptr[0]))
      break;
    rptr += nread;
  }
  rptr[0] = 0;
  return tread;
}
Verwijderd schreef op 31 augustus 2002 @ 16:38:
Is er geen functie om op te vragen hoeveel bytes je nog kunt lezen voordat de stream leeg is? Ik weet niet hoe dat onder linux werkt (sockets zijn nou eenmaal OS specific)...
Anders moet je een non-blocking read doen en met semaforen werken, je kan een openstaande read dan cancelen na een timeout periode...
Dat zou dus niet noodzakelijk moeten zijn, een telnet verbinding naar een willekeurige ftp-server levert een aantal lijnen op, waarna hij meteen verder gaat met het lezen van gebruikers invoer.

Verwijderd

Topicstarter
Verwijderd schreef op 31 augustus 2002 @ 17:10:
[...]
Je moet de socket non-blocking instellen
Zoek maar eens op O_NONBLOCK of check de manual page van fcntl.
Maar als er dan door een netwerk error eventjes geen invoer is, houd mijn functie er mee op en lijkt het of de server geen data meer in zijn buffer heeft wat door mijn client gelezen moet worden. Er is dus geen protocol onafhankelijke manier om er achter te komen of de server-host nog data klaar heeft liggen die ik zou moeten kunnen ontvangen?

Ik ga toch eens de source van telnet doorspitten...

Verwijderd

Verwijderd schreef op 31 augustus 2002 @ 17:15:
Maar als er dan door een netwerk error eventjes geen invoer is, houd mijn functie er mee op en lijkt het of de server geen data meer in zijn buffer heeft wat door mijn client gelezen moet worden. Er is dus geen protocol onafhankelijke manier om er achter te komen of de server-host nog data klaar heeft liggen die ik zou moeten kunnen ontvangen?
Nee, want hoe wil je dat implementeren? Dat is gewoon een netwerkkwestie. Dat kan niet. Simpel. ;).
Ik ga toch eens de source van telnet doorspitten...
Telnet gebruikt (neem ik aan) minstens twee threads, eentje om te lezen en eentje om te schrijven. :P.

Verwijderd

Verwijderd schreef op 31 augustus 2002 @ 17:15:
[...]

Maar als er dan door een netwerk error eventjes geen invoer is, houd mijn functie er mee op en lijkt het of de server geen data meer in zijn buffer heeft wat door mijn client gelezen moet worden. Er is dus geen protocol onafhankelijke manier om er achter te komen of de server-host nog data klaar heeft liggen die ik zou moeten kunnen ontvangen?

Ik ga toch eens de source van telnet doorspitten...
Of je functie er mee stopt of niet heb je zelf in de hand lijkt me.

Als er netwerk problemen zijn zul je (bij gebruik van TCP/IP, UDP is een ander verhaal) na een tijdje alsnog de data ontvangen, of je ontdekt bij het doen van een read dat de verbinding daadwerkelijk verbroken is.

Zoals hierboven gezegd kan je natuurlijk een time-out gebruiken (zie ook man select). Normaal gesproken weet je meestal door het protocol (op bericht niveau) of je nog iets te verwachten hebt of niet.

Verwijderd

Verwijderd schreef op 31 augustus 2002 @ 17:32:
Telnet gebruikt (neem ik aan) minstens twee threads, eentje om te lezen en eentje om te schrijven. :P.
Dat hangt van de implementatie af. Een lees/schrijf thread is een mogelijkheid, een andere mogelijkheid is om mbv select() op read en/of write events te wachten en ze vervolgens af te handelen.

Verwijderd

Dat zou dus niet noodzakelijk moeten zijn, een telnet verbinding naar een willekeurige ftp-server levert een aantal lijnen op, waarna hij meteen verder gaat met het lezen van gebruikers invoer.
Dat wil toch niet zeggen dat er onderwater geen timeout procedure zit? Gewoon een aparte thread spawnen die de verbinding afhandelt, dan blijft de main thread beschikbaar voor het afhandelen van user events.
Pagina: 1