Läsning från socket

Tråden skapades och har fått 5 svar. Det senaste inlägget skrevs .
1

Idag tog jag en titt på Berkeley sockets. Jag har ingen större erfarenhet av sockets sedan tidigare så det var helt nytt. När jag skulle läsa från en socket stod jag inför problemet att jag inte visste hur långt jag skulle läsa.

Genom att använda ioctl tar jag reda på hur många byte som kan läsas. Men det känns inte som en alltför snygg lösning. Hur bör man göra detta?

int available = 0, result;
while (available == 0)
    ioctl (fd, FIONREAD, &available);
char buffer[available+1];

result = read (fd, buffer, available);
if (result == -1)
{
    fprintf (stderr, "Fel vid läsning.\n");
    return -1;
}

buffer[result] = '\000';
  • Medlem
  • Uppsala
  • 2008-06-15 22:45

Nu var det ett tag sedan jag skrev sockets med c/objective-c
Det blir mycket kod att skriva men följande upplägg är vettigt imho:

if(poll(socket..)>0) {
while(read(socket)>0) {
// spara undan read buffer ..
}
}

dvs, tanken är att använda poll för att kolla om det finns trafik på socket:en och i så fall läsa in x antal bytes i en buffer och sedan processa den. Det finns inget gylleneregel för att ta reda på hur mycket som finns eftersom det alltid kan komma mer på en öppen socket och beteendet styrs hela tiden av protokollet.

Hoppas det hjälpte något.. inser att det är lite sent och man inte förklarar så bra.

  • Medlem
  • Stockholm
  • 2008-06-15 23:30

Det normala är att man tar en buffert som är rimligt stor för det man tänker sig läsa, säg 4kB kanske, och bara läser. Som returvärde får man hur många bytes som det fanns att läsa och som fyllts i.

Alltså så här:

#define BUFLEN 4096

char[BUFLEN] buf;
int len;

len = read (fd, buffer, BUFLEN);
if (len == -1) {
return -1;
}
buf[len] = '\0';

  • Medlem
  • Sollentuna
  • 2008-06-16 15:59
Ursprungligen av bengtb:

Det normala är att man tar en buffert som är rimligt stor för det man tänker sig läsa, säg 4kB kanske, och bara läser. Som returvärde får man hur många bytes som det fanns att läsa och som fyllts i.

Alltså så här:

#define BUFLEN 4096

char[BUFLEN] buf;
int len;

len = read (fd, buffer, BUFLEN);
if (len == -1) {
   return -1;
}
buf[len] = '\0';

Och vad händer när du läser 4096 tecken?

Nåväl. Skaffa någon av Richard Stevens böcker om UNIX Network programming.

Något i stil med detta alltså?

int result, p;
struct pollfd fds[1];

fds[0].fd = fd;
fds[0].events = POLLIN;

do
{
    p = poll (fds, 1, 1000);
    
    if (p == -1)
    {
        fprintf (stderr, "Fel vid poll\n");
        return -1;
    }
    else if (p > 0)
    {
        char buffer[4096];
        
        result = read (fd, buffer, 4095);
        if (result == -1)
        {
            fprintf (stderr, "Fel vid läsning\n");
            return -1;
        }
        
        buffer[result] = '\0';
        
        printf ("%s", buffer);
    }
}
while (p > 0);
  • Medlem
  • Stockholm
  • 2008-06-16 14:36

Jag skulle ta bort anropet till poll() och logiken runt som kollar vad poll() returnerar. Den tillför ingenting i ditt exempel.

Sista argumentet till read() bör lämpligen vara sizeof(buffer)-1 så det inte blir något fel då du ändrar storleken på variabeln.

Om du gör $ man 2 read
så ser du att read returnerar 0 om du får end of file (anslutningen stängs). Se till att testa på det så du inte får en loop.

(Allokera buffern till buffer[4097] så att du kan läsa hela jämna block. Detta är en onödig överflödig förbättring. )

1
Bevaka tråden