tags:

views:

98

answers:

5
+3  Q: 

Read from socket

I need to read from an AF_UNIX socket to a buffer using the function read from C, but I don't know the buffer size.

I think the best way is to read N bytes until the read returns 0 (no more writers in the socket). Is this correct? Is there a way to guess the size of the buffer being written on the socket?

I was thinking that a socket is a special file. Opening the file in binary mode and getting the size would help me in knowing the correct size to give to the buffer?

I'm a very new to C, so please keep that in mind.

A: 

you are correct, if you don't know the size of the input you can just read one byte each time and append it to a larger buffer.

yurib
A: 

read N bytes until the read returns 0

Yes!

One added detail. If the sender doesn't close the connection, the socket will just block, instead of returning. A nonblocking socket will return -1 (with errno == EAGAIN) when there's nothing to read; that's another case.

Opening the file in binary mode and getting the size would help me in knowing the correct size to give to the buffer?

Nope. Sockets don't have a size. Suppose you sent two messages over the same connection: How long is the file?

Andres Jaan Tack
A: 

I think the best way is to read N bytes until the read returns 0 (no more writers in the socket). Is this correct?

0 means EOF, other side has closed the connection. If other side of communication closes the connection, then it is correct.

If connection isn't closed (multiple transfers over the same connect, chatty protocol), then the case is bit more complicated and behavior generally depends on whether you have SOCK_STREAM or SOCK_DGRAM socket.

Datagram sockets are already delimited for you by the OS.

Stream sockets do not delimit messages (all data are an opaque byte stream) and if desired one has to implement that on application level: for example by defining a size field in the message header structure or using a delimiter (e.g. '\n' for single-line text messages). In first case you would first read the header, extract length and using the length read the rest of the message. In other case, read stream into partial buffer, search for the delimiter and extract from buffer the message including the delimiter (you might need to keep the partial buffer around as depending on protocol several command can be received with single recv()/read()).

Is there a way to guess the size of the buffer being written on the socket?

For stream sockets, there is no reliable way as the other side of communication might be still in process of writing the data. Imagine the quite normal case: socket buffer is 32K and 128K is being written. Writing application would block inside send()/write(), the OS waiting for reading application to read out the data and thus free space for the next chunk of written data.

For datagram sockets, one normally knows the size of the message beforehand. Or one can try (never did that myself) recvmsg( MSG_PEEK ) and if the MSG_TRUNC is in the returned msghdr.msg_flags, try to increase the buffer size.

Dummy00001
+1  A: 

On common way is to use ioctl(..) to query FIONREAD of the socket which will return how much data is available.

int len = 0;
ioctl(sock, FIONREAD, &len);
if (len > 0) {
  len = read(sock, buffer, len);
}
epatel
Hi, and thank you.What's the fourth argument in read?
Alberto
@Alberto, ah, that's a typo. Should only be 3 for read, I wrote `recv` first...
epatel
A: 

One way to read an unknown amount from the socket while avoiding blocking could be to poll() a non-blocking socket for data.

E.g.

char buffer[1024];
int ptr = 0;
ssize_t rc;

struct pollfd fd = {
   .fd = sock,
   .events = POLLIN
};

poll(&fd, 1, 0); // Doesn't wait for data to arrive.
while ( fd.revents & POLLIN )
{
   rc = read(sock, buffer + ptr, sizeof(buffer) - ptr);

   if ( rc <= 0 )
      break;

   ptr += rc;
   poll(&fd, 1, 0);
}

printf("Read %d bytes from sock.\n", ptr); 
Maister