MRalwasser
MRalwasser

Reputation: 15973

Sockets: Why does a blocking read() fail with ENOTCONN?

I am trying to read from a blocking socket, but I am wondering that read() returns -1, which I think means that there's currently no data to read - I would expect that it blocks until it can read the amount of bytes.

I also tried ensuring that the socket is in blocking mode and that a high timeout is set using:

int setBlockingIO(int fd)
{
       int flags = fcntl(fd, F_GETFL);
       fcntl(fd, F_SETFL, flags & (~O_NONBLOCK));
       int nTimeout = 30000; // 30 seconds
       setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int));
}

But this hasn't changed anything.

My question:

I know that there's another question on this topic, but there I cannot find the answer for my question.

UPDATE

Without setting a timeout, read() also returns (subjectivly) immediately -1

UPDATE 2

errno is 107 (ENOTCONN, Transport endpoint is not connected). But the client side has not closed the connection in the meanwhile (ensured by a long sleep() after write() )

Upvotes: 2

Views: 4656

Answers (6)

tvn
tvn

Reputation: 634

read() could block, so if there's no data available it will return -1 and set errno to EAGAIN or EWOULDBLOCK.

If you wand to use read(), you could use select() or poll() to wait for availability of data on the socket.

Upvotes: 0

MRalwasser
MRalwasser

Reputation: 15973

I've solved the problem.
Thank you for all your comments, they had been a great help.

The problem was the usage of the wrong file descriptor.

I passed the file descriptor of the server socket to read(), instead of the file descriptor of the client socket which accept() returned.

Upvotes: 0

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215387

What do you expect? You said you have a non-blocking socket so of course it does not block. The behavior for a non-blocking socket on read is to immediately return with some data (possibly shorter than the requested amount) if data is available to read, and to return -1 with errno set to EAGAIN or EWOULDBLOCK if no data is available.

If you don't want non-blocking behavior, why did you set the socket to be non-blocking?

Edit: Grr, you've changed your question. The reason for ENOTCONN is that you're trying to read from a socket that is not connected. Unless a socket was obtained by accept or socketpair, you must call connect on it to connect it to a remote address before read will work.

Upvotes: 4

Jason
Jason

Reputation: 32530

It means that either there was a time-out, or possibly a signal interrupted the read. You can use the results of errno in errno.h to see what the error is, and if you want the error in a human-readable formating, you can use either strerror() or perror() from string.h or stdlib.h

Update: According to the POSIX specification, you should be passing a struct timeval (defined in sys/time.h) set to the desired number of seconds and microseconds before a timeout occurs to setsockopt when specifying the SO_RCVTIMEO flag rather than casting an int to a const char*. So even though your client may be mis-behaving and causing a different error right now, you could still end up with problems further down the line if you're sending the wrong argument types to the function.

Upvotes: 3

Mel
Mel

Reputation: 6167

The reason is in errno. Likely scenarios:

  • [ECONNRESET] The d argument refers to a socket, and the remote socket end is forcibly closed.
  • [EAGAIN] The file was marked for non-blocking I/O, and no data were ready to be read.

Basically, you make non-blocking blocking using:

do
{
    read(...);
} while(errno == EAGAIN);

Upvotes: 2

Brian Roach
Brian Roach

Reputation: 76908

It returns -1 when it times out.

Don't set a timeout and it will block forever (Well, at least while the socket is still connected, anyway).

Upvotes: 1

Related Questions