7

I made an iPhone client connect to a server using GCDAsyncSocket. The server is running .Net on a Windows server. The connect is good and it sends data well too.

I then tell the client to go into receive directly after the send...

[sock readDataToData:[GCDAsyncSocket LFData] withTimeout:15 tag:1]; 

I also have this set up to receive:

- (void)onSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data 
withTag:(long)tag 

and also:

   - (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag 

If I wait for the time out the time out method is called.

If I send data from the server, the timeout is not called, so I assume the client has seen something, but there is no indication of that on the client side.

I also added:

- (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength: (NSUInteger)partialLength tag:(long)tag 

hoping I would see a partial packet but this does not get triggered either.

As I mentioned above the timeout does not trigger if I send something from the server to the client. However I would have thought it would also timeout if it hasn't received the terminator character. I also tried reading with a length of 3 but that didnt make any difference.

The GCDAsyncSocket is the the problem. AsyncSocket seems to work ok.

Maybe its the init is wrong?

dispatch_queue_t mainQueue = dispatch_get_main_queue();

asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]

Any ideas what I did wrong?

I put a post on the goggle code for this but there isnt any activity so not sure if I will get an answer or not.

Ideally if anyone has a sample code that the receives works that would be great! thank you!

Mark Worsnop
  • 4,407
  • 15
  • 54
  • 79

6 Answers6

10

Maybe there was something wrong with the spelling. (So this happened to me and I was searching for hours until I've seen the small difference)

GCDAsyncSocket renamed all delegate callbacks from onSocket to socket to match Apples naming style.

In your example above you have mentioned

- (void)onSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 

rename it to

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 

This should resolve that problem.

And in my code I've had another problem, too. Be sure the object, which calls GCDAsyncSocket, is still alive while you are connecting. GCDAsyncSockets delegate is a weak reference to your object. And because its async, the delegate can become zero (autorelease, or the instance was created inside a method which is already left) while the socket is responding. As result it appears to not be called, but the class which started the socket is already deallocated from memory. This happens especially if you are using ARC together with GCDAsyncSocket.

Hope this helps

JackPearse
  • 2,922
  • 23
  • 31
  • That information about weak reference helped me out. I'd have never found that. Thanks – Darren Sep 28 '12 at 22:04
  • A thousand appreciations! This was holding me back. – VaporwareWolf Feb 15 '14 at 00:13
  • GCDAsyncSockets delegate is a weak reference got me lost! For those who is still struggling, as @JackPearse already said, the newSocket in didAccept method will be cleaned up if it leaves the method by ARC, which is a garbage collector. You have to assign it to class's member variable to make sure ARC won't clean up your newSocket. – AndaluZ Apr 18 '14 at 13:47
  • saved a life. !!! – Ashish Ramani May 11 '22 at 07:10
3

I had the same problem and was ready to give up. My problem was server side. In my delegate method onSocket:didAcceptNewSocket: I was calling a read on the wrong socket. This solved it.

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
    NSLog(@"Connection Socket connected to ipad at %@",[newSocket connectedHost]);
    _ipadSocket = newSocket;
    [_ipadSocket setDelegate:self];

    //***This code was the faulty line. I was calling listen on sock not newSocket
    [_ipadSocket readDataToData:[AsyncSocket CRLFData] withTimeout:10 tag:0];
}
Corey Zambonie
  • 614
  • 5
  • 17
  • Yes, I was stuck on this too. It's not clear from the AsyncSocket "RUNLOOP" examples if this syntax is correct, though. For example, it appears the `newSocket` delegate is inherited. But thanks for pointing the way! – MoFlo Jan 30 '14 at 15:57
  • Thanx, I was also calling readData on Sock instead of "newSocket" – Moaz Saeed Mar 31 '15 at 09:59
3

Are you sure your server is sending data terminated with just a LineFeed and not a CRLF? Or perhaps the data you are sending back from your server isn't terminated with anything? readDataToData will wait until it hits that terminating character in the received data.

Here's the code I'm using to connect. I've stripped out what I don't think is necessary - hopefully I've not taken out anything important.

Init socket

asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

Connect

[asyncSocket connectToAddress:addr error:&err]

On connection

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
    connected = YES;

Sending (without timeout)

[asyncSocket writeData:dataData withTimeout:-1 tag:0];

Request to read the data

[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:30.0 tag:0];

Data has come through (I'm just sending strings)

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Nick Bull
  • 4,276
  • 1
  • 18
  • 25
  • Yes its for sure sending correctly. I tried using telnet to connect to the server and all is good. I also switched the .h and .m to use the older version without the GDC and that works. – Mark Worsnop Jul 01 '11 at 15:37
  • @Mark Worsnop Check out the updated answer - I've included the code that I'm using to connect and send/receive data. Hopefully something might help! – Nick Bull Jul 01 '11 at 16:58
  • I changed to the AsyncSocket class without the GCD and it works more or less. The NSData seems to be fussy about how you set that, but leaving it simple it does work. Then I changed back to the GCD class and same problem. – Mark Worsnop Jul 01 '11 at 19:11
  • I'm not sure what else to suggest. The only problem I had was over bluetooth with iOS5, but that's still under NDA so I can't talk about that. – Nick Bull Jul 02 '11 at 11:42
  • this code works for me… I just needed to make sure all the strings I sent out are attached with \r\n. – T1000 Jul 15 '11 at 05:46
  • @T1000 you can change that if necessary by chaning the CRLFData to be LFData or CRData in the readDataToData method. – Nick Bull Jul 15 '11 at 08:23
  • My problem turned out to be that I wasn't explicitly telling it to read data. Adding [sock readDataWithTimeout:-1 tag:0] did the job. –  Sep 04 '13 at 05:38
1

Add :

[sock readDataWithTimeout:-1 tag:0];

at the end of didConnectToHost.

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //Your Code

    [sock readDataWithTimeout:-1 tag:0];
}
itsji10dra
  • 4,603
  • 3
  • 39
  • 59
  • if anyone is having same issue in 2021, this might still work for you, it definitely did for me – n3dx Sep 08 '21 at 06:12
1

I think the issue is coming from what you send. If the content contains a LF somewhere in your file, the read will end when it reads the LF. You should base64 encode before sending your file or read until a size.

Pascal
  • 11
  • 1
0

I have developed almost the same code, side server ios side client vb net. From vb.net i send a file of 147 kb with metod socket.sendfile ,while in ios a use AsyncSocket so:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
{

        [sock readDataToData:[AsyncSocket CRData] withTimeout:-1 tag:0]; 

        [dataFile appendData:data];
}

I don't have nobody problem with connect and start send/receive,but my only problem is that I receive 152 kb if I use CRData and 143 kb if I use LFData delimiter.

The answer is this how make to add delimiter in vb net when i send the file?

shanethehat
  • 15,460
  • 11
  • 57
  • 87
Falco
  • 149
  • 3
  • 13