Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

socket connect() returning 0 even after peer reset

I have an iPad app in which I'm creating and connecting a posix socket. Calls to connect(...) are not responding as expected when the remote device rejects the connection attempt.

A simplified example of how I'm creating and connecting the socket:

struct sockaddr_in server;
server.sin_family = AF_INET;

int socket = socket(AF_INET, SOCK_STREAM, 0);
if(socket < 0)
{
  NSLog(@"socket create failed: %s", strerror(errno));
}
else if(inet_aton(mAddress, &server.sin_addr))
{
  server.sin_port = htons(mPortNumber);
  if(connect(socket, (struct sockaddr *)&server, sizeof(server)) == -1)
  {
    NSLog(@"connect() failed: %s", strerror(errno));
  }
  else
  {
    NSLog(@"connect() succeeded");
  }
}

In most cases, the above example works: e.g. for a remote device (hereafter referred to as 'the server') which is accepting connections, connect() returns 0 as expected. For a non-existent address, connect() blocks for a while then returns -1, and errno is ETIMEDOUT.

From the docs, if the server rejects the connection attempt I would expect connect() to return -1 and for errno to be ECONNREFUSED or perhaps ECONNRESET. Instead, connect() returns 0.

I've WireSharked the TCP conversation multiple times and can confirm that only ever consists of two packets:

Client (iPad) -> Server: SYN, ACK

Server -> Client (iPad) : RST, ACK

Why does connect return 0?

Update: Connecting to the same server from a different client, e.g. Qt on Windows (winsock?) or Mac OSX (also posix) works as expected: i.e connect() returns -1, ECONNREFUSED. This leads me to believe it's a problem with the iPad end rather than the server end.

like image 339
sam-w Avatar asked Sep 02 '13 12:09

sam-w


People also ask

How do I return 0 in RECV?

Upon successful completion, recv() returns the length of the message in bytes. If no messages are available to be received and the peer has performed an orderly shutdown, recv() returns 0.

What causes Connection closed by peer?

The error message "Connection reset by peer" appears, if the web services client was waiting for a SOAP response from the remote web services provider and the connection was closed prematurely. One of the most common causes for this error is a firewall in the middle closing the connection.

What does RECV return when there is still data in the buffer but the other side has closed the socket?

Return value If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.


1 Answers

I think you should create the socket like this, note the third parameter.

socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

At the end of the day, it really does not matter that connect() returns 0 for rejected connection. Consider this: Let's say connect() succeeds, tcp connection is established and call returns 0. However, server immediately resets or disconnects before your code has change to call write or read on the socket. The next write fails with EPIPE and read returns 0. You need to handle this case anyway.

I assume you've read this, but note that are more caveats in using POSIX sockets in iOS: https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/CommonPitfalls/CommonPitfalls.html

like image 117
Teemu Ikonen Avatar answered Oct 14 '22 15:10

Teemu Ikonen