Multithreading with CocoaAsyncSocket

CocoaAsyncSocket is a fantastic socket library for Cocoa (iOS and MacOS). It comes in RunLoop and GCD flavours, but either way its asynchronous, which means that you can fire off and receive data without your code blocking (which means your code can get on with other things, like providing GUI interactivity, etc.)

However, one of the problems I found with CocoaAsyncSocket (using the RunLoop version) was that despite its asynchronous nature, when building a server application handling multiple sockets that also required interactivity, managing a large number of sockets and packets could cause significant slowdown to my app.

To resolve this, I decided to move my RunLoop-based AsyncSocket instances onto a separate thread. Unfortunately, this is not a particularly well-documented procedure. After some initial frustration, I switched my app over to the GCD version, which solved the slowdown problem but introduced a whole host of new issues.

I returned to the RunLoop-based CocoaAsyncSocket library and will now share how to move your RunLoop-based AsyncSockets onto their own separate thread.

First, you need to create a separate thread for your socket to run in. You would normally put this in the init method of whatever class is using the socket (you also need to create an ivar of type NSThread called socketsThread to hold a reference to this new thread as we will need to pick it up later):

socketsThread = [[NSThread alloc] initWithTarget:self selector:@selector(socketsThread) object:nil];
[socketsThread start];

The first line creates a new thread running the socketsThread method, and the second line starts the new thread. Simple enough!

Next, you need to actually provide your socketsThread method. You should add this to the same class (since you specified the target as self in the previous snippet) and also add another ivar of type NSRunLoop called socketsRunLoop as again, we will need this later (and of course you need your socket ivar of type AsyncSocket):

- (void)socketsThread {
    socket = [[AsyncSocket alloc] initWithDelegate:self];
    socket.delegate = self;
    [NSTimer scheduledTimerWithTimeInterval:DBL_MAX target:self selector:@selector(ignore:) userInfo:nil repeats:NO];
    socketsRunLoop = [NSRunLoop currentRunLoop];
    [socketsRunLoop run];
}

What’s going on here is that you are creating your new socket (this is the listening, server socket — although it doesn’t strictly need to be created here) and setting its delegate to your current class. You then schedule a timer to run for a very, very long time which will keep your RunLoop alive and stop it quitting immediately. You then get a reference to the RunLoop for this thread which is stored in the socketsRunLoop ivar and then you start the RunLoop.

At this point, everything is set up and running, so all you need to do is tell your socket and all future sockets which RunLoop it should be using:

- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket {
return socketsRunLoop;
}

This tells all sockets with their delegate set to your current class to use socketsRunLoop as its RunLoop (which runs on the socketsThread thread). Just bear this in mind if you are handling multiple sockets through the same owner class.

So from now on, your listening socket as well as all other sockets will all be using socketsRunLoop (which is on a separate thread) for handling inbound and outbound communication). What you need to remember now is that when the socket delegate methods are called, they are being called from a separate thread. This means that if you want to update the UI from a delegate method (for example onSocketDidDisconnect:), then you should use:

[self performSelectorOnMainThread:@selector(something) withObject:nil waitUntilDone:NO];

waitUntilDone is of course a matter of preference, but the important thing is that you update the UI from the main thread and not from the socketsThread, as this will cause your program to crash.

The same applies vice-versa: you cannot perform operations on the socket from the main thread (i.e. the UI thread). So let’s say you have a button which when pushed sends a packet — you cannot simply write this data to the packet from the button’s callback directly. Instead, you need to make sure that you only perform it on socketsThread. To ensure this, make sure you perform any relevant selector on the correct thread:

[self performSelector:@selector(sendMessage:) onThread:socketsThread withObject:message waitUntilDone:NO];

Again, waitUntilDone is a matter of preference but the important thing is to ensure that any interaction with the sockets is done by performing the selector on the correct thread.

I hope that this post unravels some of the mystery surrounding CocoaAsyncSocket and helps other developers to skip past some of the complexities that I had to deal with in order to get this up & running.

16 Responses to “Multithreading with CocoaAsyncSocket”

  1. Ron C says:

    Thank you for posting this – it saved my little project when I went searching for this. Until I had seen it so clearly explained, I just wasn’t getting it.

  2. sri says:

    Hi

    That’s a great post, could it be possible for you to post sample code related to server integration into app.

    Thank you so much for sharing your experience

  3. Evelyne says:

    Amazing! This blog looks just like my old one! It’s on a entirely different topic but it has pretty much the same layout and design. Great choice of colors!

    Feel free to surf to my web site: Evelyne

  4. Leonard says:

    Thank you for another excellent article. Where else could anyone get
    that kind of information in such a perfect way of writing?
    I have a presentation subsequent week, and I am at the look for such
    information.

    Also visit my blog http://www.nfljerseyswhosaleblog.com

  5. Sherrill says:

    I’m not sure where you are getting your information, but good topic. I needs to spend some time learning more or understanding more. Thanks for excellent info I was looking for this info for my mission.

    My weblog: ugg 2013

  6. Natisha says:

    Your method of describing all in this post is in fact fastidious, every one
    be able to effortlessly know it, Thanks a lot.

    my web blog: ???? ??

  7. Karol says:

    I am sure this article has touched all the internet people, its really really pleasant piece of writing on
    building up new weblog.

    Here is my webpage – ???? ??

  8. Verla says:

    Does your site have a contact page? I’m having a tough time locating it but, I’d like to send you an email.
    I’ve got some ideas for your blog you might be interested in hearing. Either way, great site and I look forward to seeing it improve over time.

    Here is my web-site – Verla

  9. Karolin says:

    Ahaa, its good dialogue regarding this piece of writing
    here at this website, I have read all that, so now me also commenting at this place.

    my website – ??

  10. Angela says:

    Good day! I could have sworn I’ve been to this blog before but after browsing through some of the articles I realized it’s new to me.

    Anyways, I’m certainly delighted I found it and I’ll be bookmarking it
    and checking back regularly!

    Visit my web blog; ugg

  11. Hollis says:

    I will right away grasp your rss feed as I can’t in finding your e-mail subscription hyperlink or newsletter service. Do you have any? Kindly let me understand in order that I may just subscribe. Thanks.

    Also visit my homepage … http://www.kochipakkeji.com/

  12. Franziska says:

    These are truly enormous ideas in concerning blogging.
    You have touched some good points here. Any way keep
    up wrinting.

    My blog post :: Coach ???

  13. Paulie says:

    Definitely consider that which you stated. Your favorite justification appeared to be on the internet the simplest thing to keep in mind of. I say to you, I definitely get irked even as other people think about issues that they plainly do not realize about. You controlled to hit the nail upon the highest and also defined out the whole thing with no need side-effects , folks can take a signal. Will likely be again to get more. Thanks

  14. Rocco says:

    Discover people who definitely nostalgic whenever they are available across
    1985 Air jordans. Once you comprehend, it is easier to buy the ornaments of choice.

    Ralph Lauren, Burberry and Liz Claiborne, have added sports lines.
    Wearing nike, you will become the fixation of the eyes.
    http://dgaming.za.pl/profile.php?mode=viewprofile&u=2019

  15. Adell says:

    Subsequent to that footwear and / or products when it sheets to protected system.

    Think out of the box and hit upon unique corporate gift giving.

    Number of of million, as to Wall surface Street’s predicted. But at start off of this coming year, my most appropriate last season well before Jr. http://showmeyourart.com/groups/celine-bags-for-providers-antique-model/

  16. Harriet says:

    A great thing about the best bags is a capability to fit
    your recipient’s lifestyle. Also added one tassel design, generous of jumping flow. These bags are advantageous not only for your brand, but as well for your recipients. Purchase your current foods along with points. http://bratsk.com/user/70992

Leave a Reply