I am using TCP short connection to send data to a host. When I want to send a data to a host I will instantiate a socket, store the socket instance to an array and then remove it later on when the data is written successfully.
This is how I did it:
- (void)connectAndSendData:(NSData *)data
GCDAsyncSocket *asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
[_connectionDataToBeSentMap setObject:data forKey:[NSValue valueWithNonretainedObject:asyncSocket]];
if(![asyncSocket connectToHost:_host onPort:TCP_COMMUNICATION_PORT withTimeout:TCP_CONNECTION_TIMEOUT error:&error])
NSLog(@"TCPShortConnection - failed when attempting to connect to host with IP %@", _host);
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
if(err.code == GCDAsyncSocketConnectTimeoutError)
// NSLog(@"TCPShortConnection - on connection timed out");
// NSLog(@"TCPShortConnection - on disconnection of socket with host %@", _host);
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x258d9b0b 0x25096dff 0x257ea6d3 0x257ff033 0xfae43 0x1ca94d 0x4ccba7 0x4d8eff 0x4d87f1 0x2560ae0d 0x2560a9fc)
libc++abi.dylib: terminating with uncaught exception of type NSException
Guess: you are accessing your
NSMutableArray from different threads
NSMutableArray is not thread safe, concurrent reading and writing is not safe - as may occur if you are accessing the array from a GCD concurrent queue.
GCDAsyncSocket as its name suggests uses GCD. In particular delegate calls are dispatched on a GCD queue set by the user and this queue may be concurrent.
You are setting one of the global concurrent queues as the delegate queue.
Solution: You should first determine whether you should be using an array, we cannot determine that for you. If you need the array then it needs to be thread safe. A simple way to do this is:
When you create the array also create a sequential GCD queue just for this array.
To perform an array method which reads from the array perform a synchronous dispatch on the array's sequential queue. You can return the result from the dispatched block using a
To perform a write operation on the array use an asynchronous dispatch to the array's queue.
This simple model ensures that no two operations on the array can occur concurrently and all reads and writes occur in the order they are dispatched.
As I stated at the start, I'm guessing concurrent access to the array is your problem, you will need to determine that yourself. If it is this should fix it.