Can't rebind a POSIX socket to a port on iOS 10.2.1

Hello guys,


My app can't bind a POSIX TCP socket to a port it successfully bound in the previous run on iOS 10.2.1 only. No problem with it on iOS 9.2.1. I always get an error 'Address already in use'. I use PF_INET, SOCK_STREAM, IPPROTO_TCP socket and I tried to use flags SO_REUSEADDR nad SO_REUSEPORT - both at once and separately. None of it helped.


Any suggestions?

I tried this on 10.3.1 and it’s working for me. I’ve pasted in my code below, so you can try it for yourself. Here’s how I tested this:

  1. I ran the app and started the listener

  2. From my Mac I used telnet to connect to the server; the server immediately closes the socket, which puts the connection in the

    TIME_WAIT
    state
  3. I stopped the listener

  4. I started the listener again

Without the

SO_REUSEADDR
the
bind
in step 4 consistently fails with
EADDRINUSE
. With the
SO_REUSEADDR
it works as expected.

btw Is there a reason you’re using BSD Sockets for your listener rather than NSNetService. The latter is much easier.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
#import "MainViewController.h"

#include <sys/socket.h>
#include <netinet/in.h>

@interface MainViewController ()

@property (nonatomic, assign, readwrite) int listener;

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.listener = -1;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    #pragma unused(tableView)
    #pragma unused(indexPath)

    if (self.listener == -1) {
        [self start];
    } else {
        [self stop];
    }

    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (void)start {
    NSLog(@"listener will start");

    self.listener = socket(AF_INET, SOCK_STREAM, 0);
    assert(self.listener >= 0);

    struct sockaddr_in addr = {
        .sin_len = sizeof(struct sockaddr_in),
        .sin_family = AF_INET,
        .sin_port = htons(12345),
        .sin_addr.s_addr = INADDR_ANY
    };
    static const int kOne = 1;
    int err = setsockopt(self.listener, SOL_SOCKET, SO_REUSEADDR, &kOne, sizeof(kOne));
    assert(err == 0);
    err = bind(self.listener, (const struct sockaddr *) &addr, sizeof(addr));
    if (err < 0) {
        NSLog(@"bind failed: %d", errno);
        [self stop];
        return;
    }
    err = listen(self.listener, 5);
    if (err < 0) {
        NSLog(@"listen failed: %d", errno);
        [self stop];
        return;
    }
    [NSThread detachNewThreadSelector:@selector(rejectThreadEntry) toTarget:self withObject:nil];
    NSLog(@"listener did start");
}

- (void)rejectThreadEntry {
    NSLog(@"reject will start");
    // This code is /very very/ bogus and should not be used in a real app.  Specifically,
    // there's a race between this thread and the main thread calling `close` that could
    // result in us calling `accept` on some unrelated file descriptor.
    int fd = self.listener;
    do {
        int fd2 = accept(fd, NULL, NULL);
        if (fd2 >= 0) {
            int junk = close(fd2);
            assert(junk == 0);
            NSLog(@"reject did reject");
        } else {
            NSLog(@"reject did error: %d", errno);
            break;
        }
    } while (YES);
    NSLog(@"reject did stop");
}

- (void)stop {
    int junk = close(self.listener);
    assert(junk == 0);
    self.listener = -1;
    NSLog(@"listener stopped");
}

@end

Can Poll be used in IOS 10.3.1 . Please let me know , Thanks.

Can Poll be used in IOS 10.3.1

I presume you’re talking about traditional System V

poll
here. If so, the answer is “yes”. Having said that, most iOS apps don’t use this because:
  • There are lots of nicer high-level alternatives

  • Even at the BSD layer there are nicer alternatives (GCD and

    kqueue
    )
  • Traditional BSD code uses

    select

ps It would help if you started a new thread for new questions rather than piggybacking on some unrelated thread.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Can't rebind a POSIX socket to a port on iOS 10.2.1
 
 
Q