sam-w
sam-w

Reputation: 7687

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.

Upvotes: 7

Views: 1545

Answers (1)

Teemu Ikonen
Teemu Ikonen

Reputation: 11929

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

Upvotes: 1

Related Questions