GCDAsyncSocket readData not called - ios

I'm trying to send a message to a server and receive a response using my iPhone. I can connect to the server using:
telnet 123.123.123.1 6000
Trying 123.123.123.1...
Connected to 123.123.123.1.
Escape character is '^]'.
?VERSION
OK
VERSION=PROTOCOL: 1.1.0
?VERSION is my question
OK states it received and understood the question
VERSION= is the response from the server
so I'm trying to do the same thing but with xcode
So I have this in my viewDidLoad
dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:mainQueue];
asyncSocket.delegate = self;
NSString *host = #"123.123.123.1";
uint16_t port = 6000;
NSLog(#"Connecting to \"%#\" on port %hu...", host, port);
NSError *error = nil;
if (![asyncSocket connectToHost:host onPort:port withTimeout:5.0 error:&error])
{
NSLog(#"Error connecting: %#", error);
}
else
{
NSLog(#"Connecting...");
}
And I have the following code showing it connected
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:
(UInt16)port
{
NSLog(#"socket:%p didConnectToHost:%# port:%hu", sock, host, port);
// We're just going to send a test string to the server.
NSString *myStr = #"?VERSION";
NSData *myData2 = [myStr dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:myData2 withTimeout:-1 tag:0];
}
And the following to show it wrote
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
NSLog(#"WRITING");
[asyncSocket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:0];
}
Sadly this never gets called
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *tempString = [[NSString alloc]initWithData:data
encoding: NSUTF8StringEncoding];
}
I'm lost and really need some assistance

It is because you say write AND read at the same time. First call [asyncSocket writeData:myData2 withTimeout:-1 tag:0]; and in didWriteDataWithTag call [asyncSocket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:0];. You are on one thread - dispatch_get_main_queue() - it can't do two things at one time.

Related

iOS: GCDAsyncSocket and its tag

In my app I'm using GCDAsyncSocket and I write and read in this way:
NSData *bufferWriteData = [NSData dataWithBytesNoCopy:bufferWrite length:17 freeWhenDone:YES];
[self.socket writeData:bufferWriteData withTimeout:-1 tag:1];
[self.socket readDataWithTimeout:-1 tag:1];
after I read in the delegate method the data:
- (void) socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSLog(#"did read data");
if (tag == 1){
//analyze my data...
[self.socket readDataWithTimeout:-1 tag:1];
}
inside this delegate method I recall the "readDataWithTimeout" so in this way I read all data.
The problem id when I do a new call, if I do:
[self.socket writeData:bufferWriteData withTimeout:-1 tag:2];
[self.socket readDataWithTimeout:-1 tag:2];
I start a new write and a new read with tag = 2;
When the delegate method "didReadData" is called my code enter inside the block of tag = 1; it seems that it don't recognize the new tag.
Why it happen?
There are several ways to handle this. In your case, the best way probably just used a terminator to indicate the end of that data segment. You can read up there: TCP is a stream.
NSData *MyCommandTerminator(void)
{
return [NSData dataWithBytes:"\x0D\x0A\x0B\x0A" length:4];
}
//callback from Asyncsocket for incoming data
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag //sender and receiver
{
NSLog(#"GCDAsyncSocket didreaddata");
// do what you wish with data and read again using a terminator
[sock readDataToData:MyCommandTerminator() withTimeout:-1 tag:1]; //tag is not being used here
}
// your method to send data
-(void)sendData:(NSData *)data
{
// NSData *bufferWriteData = [NSData dataWithBytesNoCopy:bufferWrite length:17 freeWhenDone:YES];
NSLog(#"Sendata wehere _peerSocket is your instance of GCDAsyncSocket");
NSMutableData *myData = [[NSMutableData alloc] initWithData:data];
[myData appendData:MyCommandTerminator()];
[_peerSocket writeData:myData withTimeout:-1 tag:2]; // tag is not being used here
}

why GCDAsyncUdpSocket cannot send/receive packets after a while in broadcast mode?

I am using GCDAsyncUdpSocket to write a UDP socket in my app. The scenario is like this: when users click the button, it will send a broadcast packet in LAN then listen to the response, there is a server in LAN which will respond with one UDP packet. When the app receives the response, it will do something.
I set GCDAsyncUdpSocket as followings:
- (void)setupSocket
{
_udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![_udpSocket bindToPort:18686 error:&error]) {
NSLog(#"Error binding: %#",error);
return;
}
if (![_udpSocket beginReceiving:&error]) {
NSLog(#"Error receiving: %#",error);
return;
}
if (![_udpSocket enableBroadcast:YES error:&error]) {
NSLog(#"Error enableBroadcast: %#",error);
return;
}
}
then i send Packet in button action as following:
NSString *host = #"255.255.255.255";
int port = 8585;
NSString *msg = #"Hello from iOS";
NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
[_udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:0];
in
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
method i listen the port to do somethings. It works perfectly at beginning, but if you try to click the button later (about 1 hour), then it cannot send UDP packet any more.
My server in LAN will print the data received. I thought there was something wrong with send method. so i use BSD socket methods to send The data. and use GCDAsyncUdpSocket to receive the response. but the same thing happened after a while. this time i can send but cannot receive.
Am i missing something about GCDAsyncUdpSocket? why it cannot send/receive after a while? Any help would be much appreciated.
It may be some timeout setting. Implement the GCDAsyncUdpSocketDelegate protocol to fetch detailed information about what is going on.
The hard solution is to establish a new connection.

Can not read data from server using GCDAsyncSocket

I tried to connect to the server and send some information to the server(like username, password..), and the server send me back the ID (string type). The problem is I can not get the ID. Could anyone help me? I am beginner in IOS coding. Thanks.
Here is the codes:
After I click the button, it will call my own function to get serverIP which is a string and Port which is a int.
Then that function will call this function to connect the server:
(void)logInCheck {
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
uint16_t port = serverPort;
if (![asyncSocket connectToHost:serverIP onPort:port error:&error])
{
DDLogError(#"Unable to connect to due to invalid configuration: %#", error);
}
else
{
DDLogVerbose(#"Connecting...");
[self passDataToServer];
}
}
//DataPassToServer is a NSString that hold my data
(void)passDataToServer
{
NSData *requestData = [DataPassToServer dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
[asyncSocket readDataWithTimeout:-1 tag:0];
}
//this function call successfully
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
DDLogVerbose(#"socket:didConnectToHost:%# port:%hu", host, port);
}
//this function call successfully
(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
DDLogVerbose(#"socket:didWriteDataWithTag:");
}
//This function does not run !!! Nothing print out.
(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
DDLogVerbose(#"socket:didReadData:withTag:");
NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"ID = %#",response);
[asyncSocket readDataWithTimeout:-1 tag:0];
}
I don't know about your server implementation but, most implementations would read up to the first newline character before processing the request.
So make sure that your [DataPassToServer dataUsingEncoding:NSUTF8StringEncoding] includes a newline character ("\n") at the end.
Your code looks fine and works for me.

sending UDP request to 255.255.255.255 and waiting for reply in iOS

Im would to send a UDP broadcast from an iPhone, and then listen for a UDP response with a timeout period from all devices with such port opened. Does my custom device from the same subnet would answer? ( if mine is 192.168.1.100 and IP of custom device is 192.168.1.201 )
What to use "SmallSockets" or "cocoaAsyncSocket" ?
What function to use to listen for response?
Thanx!
i decided to use cocoaAsyncSocket.
To broadcast you can use:
[udpSocket sendData:datatosend toHost:#"192.168.1.113" port:port withTimeout:-1 tag:0];
to receive:
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext
{
NSString *msg = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
if (msg)
{
NSLog(#"Message = %#, Adress = %# %i",msg,host,port);
}
else
{
NSLog(#"Error converting received data into UTF-8 String");
}
}

iPad GCDAsyncSocket doesn't read

I really need some help with my project...
I need to exchange data with my server written in Java. I tried using GCDAsyncSocket, and I can send message to server, read it on server, but when server sends response to client, I can't (don't know how to) read it on client. Here is part of my code:
- (void) someMethod{
NSError *err = nil;
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
if(![asyncSocket connectToHost:#"localhost" onPort:7777 error:&err]){
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
NSString *requestStr = #"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><root><service>1</service><type>1</type><userProperties><username>ivo</username></userProperties></root>";
NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:1.0 tag:0];
[asyncSocket disconnectAfterWriting];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
if (tag == 0)
NSLog(#"First request sent");
else if (tag == 2)
NSLog(#"Second request sent");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",str);
}
Please help, if there is another way I am willing to try as I am getting desperate...
I see that you're sending XML, with no particular terminator at the end of your request data, yet you're expecting the server to send a response terminated by a \r\n?
What does the protocol specify?
Sending and receiving data over tcp is a common cause of confusion because tcp is stream based. It has no concept of individual reads/writes. It treats all data as conceptually a never ending stream. The protocol dictates message boundaries. For a better explanation, see the "Common Pitfalls" article from GCDAsyncSocket's wiki:
https://github.com/robbiehanson/CocoaAsyncSocket/wiki/CommonPitfalls
I think it will help explain a lot.

Resources