views:

1288

answers:

2

Hello, i'm trying to send/receive data over wifi to an iphone/ipodtouch app from a C# tcpip server. for this i used cocoaAsyncSocket from the google project. If i push a button and i send a request from ipod to server it returns the requested data(song title for example)..i want to know every second what song is playng...so from C# server i send at intervals of 1 second messages to my app. In my app in an timer with the interval of 1 second i call the asyncSocket read readDataWithTimeout method. My problem is that after 8-9 seconds that method is not called anymore. The connection to the server is still active and the C# server still sends data..

what i want to do is the following thing: -> winamp plays a song -> C# server asks winamp what songs is he playing and sends the song title to my app. -> iphone app receives the data and displays it

i don't know why the readDataWithTimeout method is not called anymore after a short period of time..Maybe because the short time between messages sent by the C# server?

Thank you, Sorin

+2  A: 

Several things here. First, why do this every second rather than just on song changes? This is going to be very expensive on the iPhone battery to constantly chatter this way. There's little reason to do it even on a desktop.

So if I understand correctly, iPhone connects to .NET and asks for the song. .NET returns the song and leaves socket open. Every second, .NET writes to its socket, and every second iPhone reads from its socket.

What I suspect is happening is that at some point the timeout on the readDataWithTimeout:tag: doesn't expire before the next NSTimer fires (neither has any real guarantee about when it will fire). You then probably get two readDataWithTimeout:tag: calls running at the same time, probably getting the socket delegate confused.

The better solution is a "long poll." On the iPhone side, call readDataWithTimeout:tag: with a fairly long timeout (say 30-60s). Each time it returns, just loop right back into it:

while (self.isRunning) {
    [socket readDataWithTimeout:60 tag:0];
}

Then in -onSocketDidDisconnect: and -onSocket:willDisconnectWithError:, make sure to set self.isRunning to NO. Get rid of the NSTimer entirely.

I'd still not post anything from the .NET side until Winamp actually changes songs, though. Sending the same data over and over again doesn't do any favors.

Rob Napier
hello rob, thank you for the answer.i thought about that because for example if i read the data from the socket with a timeout of 30 secs, if winamp changes a song in that timeout my ipod app will receive that data with a delay(of max 30 seconds) so it will not be updated data...how could i make the sending/reading process to and from ipod to the server in such a way that i don't do again the first mistake i did?Thank you, Sorin
SorinA.
to be more precise..in my app i have the situation when the C# server has to push data to the app(data that the app didn't explicitly requested by push of a button for example)
SorinA.
Calling `-readDataWithTimeout:tag:` will block for up to "timeout" seconds waiting for data. If the data shows up before that, it'll post `-onSocketDidReadData:withTag:` immediately, so there shouldn't be a delay there.
Rob Napier
A: 

i made it work..after a little more reading... so to read data when it arrives with AsyncSocket on unknown intervals i used the fallowing code(i don't know if is the best solution but it works for what i wanted):

- (void) readDataFromSocket
{
        [socket readDataWithTimeout:-1 tag:0];
}

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length])];
    NSString *msg = [[[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding] autorelease];
    if(msg)
    {
        if([msg isEqualToString:@"something"])
        {
            Do stuff
        }
        else
        {
            Do something else
            }
        }
    }
    else
    {
        NSLog(@"Error converting received data into UTF-8 String");
    }
    [socket readDataWithTimeout:-1 tag:0];
}

i call once in my application the readDataFromSocket method that calls the sockets [socket readDataWithTimeout:-1 tag:0] method. It should be called only once in the app because in the method - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag method in the last line i call again the [socket readDataWithTimeout:-1 tag:0]; which tells the socket to listen on the socket. When data arrives the socket will read it.

hope it helps someone..

SorinA.