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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With