Not able to receive response of the sent UDP packets using GCDAsyncSocket - ios

I am making an app to send UDP packets in order to switch on a LED bulb. I have been able to perform all the actions when I am connecting to the Ad-hoc created by the Wifi bridge.
Now, I want to configure the Wifi bridge so that it can connect to my main router. I have the AT command set to perform this procedure but somehow I am not able to receive the response form the Wifi bridge for the commands which I am sending to it.
The procedure is as follows:-
Step 1 : Send UDP message to the LAN broadcast IP address of "10.10.100.255" and port of 48899 => "Link_Wi-Fi"
All Wifi bridges on the LAN will respond with their details. Response is "10.10.100.254, ACCF232483E8"
Step 2 : (optional for changing settings on the wifi bridge): Then send "+ok" to the LimitlessLED Wifi Bridge. Send UDP message to the response IP address returned from step 1 "10.10.100.254" => "+ok"
Step 3 : (optional for changing settings on the wifi bridge): After that you may send AT commands (ending with \r\n) to the module.
The code for sending the UDP packets is as follows
-(void)configureWifi{
counter++;
NSString *host = #"10.10.100.255";
if ([host length] == 0)
{
[self logError:#"Address required"];
return;
}
int port = 48899; //[portField.text intValue];
if (port <= 0 || port > 65535)
{
[self logError:#"Valid port required"];
return;
}
NSString *msg = #"Link_Wi-Fi";
NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"the message sent is %#", data);
[udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:tag];
}
Now in order to setup the socket and to receive the data I am using these two delegate methods:
- (void)setupSocket
{
// Setup our socket.
// The socket will invoke our delegate methods using the usual delegate paradigm.
// However, it will invoke the delegate methods on a specified GCD delegate dispatch queue.
//
// Now we can configure the delegate dispatch queues however we want.
// We could simply use the main dispatc queue, so the delegate methods are invoked on the main thread.
// Or we could use a dedicated dispatch queue, which could be helpful if we were doing a lot of processing.
//
// The best approach for your application will depend upon convenience, requirements and performance.
//
// For this simple example, we're just going to use the main thread.
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:0 error:&error])
{
[self logError:FORMAT(#"Error binding: %#", error)];
return;
}
if (![udpSocket beginReceiving:&error])
{
[self logError:FORMAT(#"Error receiving: %#", error)];
return;
}
[self logInfo:#"Ready"];
}
and to Receive data this is the method which is note getting called after sending the UDP packets. This is the delegate method of the GCDAsyncUdpSocket class which I have used in my project in order to send and receive the UDP packets.
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (msg)
{
[self logMessage:FORMAT(#"RECV: %#", msg)];
}
else
{
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
[self logInfo:FORMAT(#"RECV: Unknown message from: %#:%hu", host, port)];
}
}
Once I am able to receive the response I will be able to send the next AT commands in order to configure the Bridge.
Thanks. Any help will be appreciated.

Here are the troubleshooting steps I recommend that you use :
1- I'm assuming you are using ARC so make sure that your udpSocket variable has a strong reference throughout the asynchronous communication. If it is being freed, then that could explain the absence of a callback.
2- Make sure the communication is really happening the way you think it is. Use a software such as Wireshark to capture the packets being exchanged on the network. This should allow you to confirm that your packets do get sent upon calling sendData: and it will also allow you to confirm whether or not you are getting a reply back.
3- Make sure you are using the GCDAsyncUdpSocket properly. Considering you want to broadcast a message, you shouldn't be calling bindToPort:error: in your setupSocket method. Instead you should be calling enableBroadcast:error:. Considering you also want to receive packets after broadcasting, you should use the connectToHost:onPort:error: method to change the state of the socket to allow for bidirectional communication. After that is done, you can replace your usage of sendData:toHost:port:withTimeout:tag: by sendData:withTimeout:tag:. Finally, you can call beginReceiving: so that the delegate gets called for any incoming packets.
4- If this still doesn't get you through it, I recommend that you read throughly the documentation of the GCDAsyncUdpSocket which is very well documented.

You can trouble shoot the problem using Wireshark or any network capture tool.
We use to work in similar kind of project where we used Wireshark extensively.
If packet has reached device(Z-Wave ) it will send out some sort of Ack.
this will help to make sure packets are getting out.

Related

Very high UDP packages loss on iOs (GCDAsyncUdpSockets)

I am working on an iPhone app for controlling physical hardware.
The routine is as follows:
app sends a specific 8-bytes "wake up" datagram on the broadcast channel, on port 8089; the message is repeatedly sent.
external hardware, which is listening to port 8089, receives the message and sends a 94 bytes datagram containing, among other stuff, the IP and MAC address of the hardware; this is also on the broadcast channel.
app stops sending the "wake up" message, stores IP, and begins communicating with the hardware via a TCP socket
The routine generally works. However, I often get an inexplicable loss of UDP packages on reception; that is, I send the 8-bytes "wake up" signal, but I don't get the 94 bytes response.
When the app works, it works perfectly: I hardly lose a single package, and if the app misses the first 94-bytes message, it gets the second or third one.
When it doesn't work, it misses all packages, constantly.
The "not-working" stage might last for minutes, or hours; I've found no apparent trigger - it's as if at some stage, with no reason, reception stops working.
Before asking here, I've done very extensive debugging. I've monitored the sockets via rvictl and tcpdump, and confirmed that my logs reflect what happens at the socket level.
To take the external hardware out of the equation, I've built a mirror app that behaves as the hardware should. I've tried changing ports, I tried to close and nil sockets all times, to reset them , to pause and restart reception. None of this worked.
I've developed my communication library with GCDAsyncUdpSocket. To be on the safe side, I've experimented also with the non GCD version; the result is the same. I built my own minimal wrapper around C sockets; I got the same behaviour.
Here is my implementation code:
GCDAsyncUdpSocket *udpSocket;
- (void)startUdpBroadcast {
if (udpSocket == nil)
{
// Setup our socket.
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
[udpSocket setIPv6Enabled:NO];
}
NSLog(#"Listening for a message on %#",[self getBroadcastAddress]);
NSError *bindError = nil;
NSError *enableError = nil;
NSError *receivingError = nil;
[udpSocket bindToPort:8089 error:&bindError];
if (bindError) {
NSLog(#"Error, can't bind: %#",[bindError localizedDescription]);
return;
}
[udpSocket enableBroadcast:YES error:&enableError];
if (enableError) {
NSLog(#"Error, can't enable broadcast: %#",[enableError localizedDescription]);
return;
}
if (![udpSocket beginReceiving:&receivingError])
{
NSLog(#"Error, can't receive: %#",[receivingError localizedDescription]);
return;
}
[self logInfo:#"Start listening to UDP boradcast channel"];
[self sendUdpSignal];
repeatedBroadcastTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(sendUdpSignal) userInfo:nil repeats:YES];
}
-(void)sendUdpSignal {
NSData* signal = [self udpBroadcastSignal] ;
NSLog(#"Send broadcast signal %# on %#",signal, [self currentNetworkSsid]);
[udpSocket sendData:signal toHost:[self getBroadcastAddress] port:8089 withTimeout:10 tag:0];
}
Do you have any suggestion?
Is there a way to make sure socket reception is never stopped?
Thanks in advance,
Davide

Receive data packets via BLE Notifications

When receiving multiple packets via BLE notifications, iOS is only giving me access to the final packet sent. I am using YMSCoreBluetooth to connect to a BLE peripheral with multiple services, each of which has multiple characteristics. I connect to the peripheral, discover the services and discover the characteristics of those services without a problem. My goal is to subscribe to a certain characteristic's notifications and receive via the notifications a series of data packets. My subscription is successful and I can see through use of NSLogs within my code that I am receiving the notifications containing the data. The issue is that when I go to access the data from each notification as it comes in, every notification gives me only the data contained in the last packet sent.
My code for receiving notifications is as follows:
- (void)notifyCharacteristicHandler:(YMSCBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(#"Error: Error in handling notification.\n%#", error);
}
else if ([characteristic.name isEqualToString:#"InterestingChar"]) {
if (self.firstNotify) {
self.mutableData = [[NSMutableData alloc] init];
self.firstNotify = NO;
}
NSData *data = [[NSData alloc] init];
data = characteristic.cbCharacteristic.value;
[self.mutableData appendData:data];
self.notifyCounter++;
NSLog(#"Notify received! Count: %ld \nData =%#",(long)self.notifyCounter,self.mutableData);
}
else NSLog(#"Other notification received");
}
For instance, if I receive 5 notifications with the following data:
1 ababababab
2 bcbcbcbcbc
3 cdcdcdcdcd
4 dedededede
5 efefefefef
My NSLog would print out efefefefef for the first notify data, efefefefef efefefefef for the second, and so on appending the last data value for each subsequent notify.
I am trying to send the notifications as quickly as possible from the peripheral using BLE. The connection interval is between 20ms and 40ms (iOS demands a range of at least 20ms) and three packets are being sent per connection interval.
EDIT:
Paulw11's suggestion worked beautifully. I fixed the issue by amending the YMSCB 'didUpdateValueForCharacteristic' method to obtain the value of the characteristic and pass it along with the pointer to the characteristic itself onto the 'notifyCharacteristicHandler' method. The amended method now looks as follows:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
__weak YMSCBPeripheral *this = self;
NSData *value = characteristic.value;
_YMS_PERFORM_ON_MAIN_THREAD(^{
YMSCBService *btService = [this findService:characteristic.service];
YMSCBCharacteristic *yc = [btService findCharacteristic:characteristic];
if (yc.cbCharacteristic.isNotifying) {
[btService notifyCharacteristicHandler:yc value:value error:error];
} else {
if ([yc.readCallbacks count] > 0) {
[yc executeReadCallback:characteristic.value error:error];
}
}
if ([this.delegate respondsToSelector:#selector(peripheral:didUpdateValueForCharacteristic:error:)]) {
[this.delegate peripheral:peripheral didUpdateValueForCharacteristic:characteristic error:error];
}
});
}
You obviously also need to amend the 'notifyCharacteristicHandler' method to accept the new argument.
Looking at the internal didUpdateValueForCharacteristic delegate method of the YMSCoreBluetooth library, it sends the data to your method using a "perform on main thread" and it doesn't capture the data - it just sends a reference to the characteristic. Also, it performs a "findCharacteristic" on the characteristic by executing a linear search through the array on the main thread even though this could have been done immediately on entering the delegate method on the current thread. Granted this isn't going to be a very big array but it seems that this library hasn't been created with performance in mind.
I suspect that you have a timing problem - by the time your method executes the data in the characteristic has been over written. If you have control over your peripheral, slow it right down for a test to see if the problem goes away.
If it is timing related then you could try a straight Core-Bluetooth implementation, or try a modification to YMSCoreBluetooth so that it captures the data earlier - perhaps if it created a copy of the peripheral at the start of didUpdateValueForCharacteristic and sent that to your method it would work.

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.

Cocoaasyncsocket multiple write operations

I have implemented gcdasynsocket in my app and performing multiple write operations. The delegate didWriteDataWithTag is called twice but didreaddata is called only once (ie) for only one write operation.
-(void)connectToHost:(NSString*)ip andPort:(NSString*)port
{
if(![asyncSocket isConnected])
{
dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];
NSError *error = nil;
uint16_t portNumber = (uint16_t)[port integerValue];
if (![asyncSocket connectToHost:ip onPort:portNumber withTimeout:-1 error:&error])
{
NSLog(#"Error connecting: %#", error);
}
else
{
NSLog(#"Connecting...");
}
}}
GCDasyncsocket delegate methods
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
NSLog(#"connected to host");
[asyncSocket writeData:dataToBeWritten1 withTimeout:-1 tag:1000];
[asyncSocket writeData:dataToBeWritten2 withTimeout:-1 tag:2000];
}
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[asyncSocket readDataWithTimeout:-1 tag:tag];
}
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
if (tag==1000)
{
NSLog(#"didReadData and tag-----%#-----%ld",data,tag);
[asyncSocket readDataWithTimeout:-1 tag:2000];
}
else if(tag==2000)
{
NSLog(#"didReadData and tag-----%#-----%ld",data,tag);
[asyncSocket readDataWithTimeout:-1 tag:1000];
}
}
I am not sure what is going wrong. Please help me to fix the issue
I think you're getting tripped up by the inner workings of the TCP protocol. TCP is a stream-based protocol, not a message-based protocol. In other words, it guarantees that bytes will arrive in the exact same order they were sent, but there are no guarantees about how those bytes will be grouped into packets or read operations.
Specifically, I suspect your two writes are being aggregated, either in the transmitter or receiver, into a single read. In other words, this behavior is entirely normal and expected.
You'll need to separate your data into logical units using some other way besides relying on every write causing exactly one read in the receiver. One common technique is to start every message with a length field that allows the receiver to not only read each message but also to know how long it is and to be able to find where the next message starts.
Here's a good explanation on how to go about doing that: Proper technique for sending multiple pieces of data of arbitrary length over TCP socket

asyncsocket ipad doesn't connect to server [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
My application times out while trying to connect to host. The timeout time is set to unlimited so I take it that the client is really just unable to connect at all.
I have an iPad app running asyncsockets and I'm trying to get it to connect to a server on my desktop also using asyncsockets. The iPad is specifically iOS 5 and is using GCD asyncsockets.
The server is being invoked through a NSRunLoop. It receives no form of connection from the client (none of breakpoints are caught like they are for telnet connections).
I'm able to telnet into the server from other machines just fine. I'm also able to connect the iPad client to host:google.com on port:80 just fine.
I've tried connecting the iPad to the server on ports 8080, 4500, and 50000 all to no success (they all work for telnet though).
I believe there is something in the server code causing this but I am not sure.
My server code is from a sample found here: http://mysterycoconut.com/blog/2010/07/tweak-away/
My client code is modified HTTP client code from the sample GCD code supplied by the asyncsockets repository: https://github.com/robbiehanson/CocoaAsyncSocket/blob/master/Examples/GCD/SimpleHTTPClient/Mobile/SimpleHTTPClient/SimpleHTTPClientAppDelegate.m
Here is my server code:
- (id) init;
{
self = [super init];
if (self != nil)
{
debugServer = [[AsyncSocket alloc] initWithDelegate:self];
connectedClients = [[NSMutableArray alloc] initWithCapacity:1];
running = false;
}
return self;
}
- (void) dealloc;
{
[self stop];
[connectedClients release];
[debugServer release];
[super dealloc];
}
- (void) startOnPort
{
if (running) return;
if (_port < 0 || _port > 65535)
_port = 0;
NSError *error = nil;
if (![debugServer acceptOnPort:_port error:&error])
return;
NSLog(#"My Awesome Debug Server has started on port %hu", [debugServer localPort]);
running = true;
}
- (void) stop;
{
if (!running) return;
[debugServer disconnect];
for (AsyncSocket* socket in connectedClients)
[socket disconnect];
running = false;
}
- (void) setPort:(int)in_port{
_port = in_port;
}
- (void)onSocket:(AsyncSocket *)socket didAcceptNewSocket:(AsyncSocket *)newSocket;
{
[connectedClients addObject:newSocket];
}
- (void)onSocketDidDisconnect:(AsyncSocket *)socket;
{
[connectedClients removeObject:socket];
}
- (void)onSocket:(AsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port;
{
NSLog(#"Accepted client %#:%hu", host, port);
NSData *welcomeData = [#"Welcome to my Awesome Debug Server\r\n\r\n"
dataUsingEncoding:NSUTF8StringEncoding];
[socket writeData:welcomeData withTimeout:-1 tag:WelcomeMsgTag];
[socket readDataWithTimeout:-1 tag:GenericMsgTag];
}
- (void)onSocket:(AsyncSocket *)socket didReadData:(NSData *)data withTag:(long)tag;
{
NSString *tmp = [NSString stringWithUTF8String:[data bytes]];
NSString *input = [tmp stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"%#",input);
if ([input isEqualToString:#"exit"])
{
NSData *byeData = [#"Bye!\r\n" dataUsingEncoding:NSUTF8StringEncoding];
[socket writeData:byeData withTimeout:-1 tag:GenericMsgTag];
[socket disconnectAfterWriting];
return;
}
[socket readDataWithTimeout:-1 tag:GenericMsgTag];
}
#end
...and here is my client code:
- (id) init
{
if (self = [super init]) {
// AsyncSocket optionally uses the Lumberjack logging framework.
//
// Lumberjack is a professional logging framework. It's extremely fast and flexible.
// It also uses GCD, making it a great fit for GCDAsyncSocket.
//
// As mentioned earlier, enabling logging in GCDAsyncSocket is entirely optional.
// Doing so simply helps give you a deeper understanding of the inner workings of the library (if you care).
// You can do so at the top of GCDAsyncSocket.m,
// where you can also control things such as the log level,
// and whether or not logging should be asynchronous (helps to improve speed, and
// perfect for reducing interference with those pesky timing bugs in your code).
//
// There is a massive amount of documentation on the Lumberjack project page:
// https://github.com/CocoaLumberjack/CocoaLumberjack
//
// But this one line is all you need to instruct Lumberjack to spit out log statements to the Xcode console.
[DDLog addLogger:[DDTTYLogger sharedInstance]];
// Create our GCDAsyncSocket instance.
//
// Notice that we give it the normal delegate AND a delegate queue.
// The socket will do all of its operations in a background queue,
// and you can tell it which thread/queue to invoke your delegate on.
// In this case, we're just saying invoke us on the main thread.
// But you can see how trivial it would be to create your own queue,
// and parallelize your networking processing code by having your
// delegate methods invoked and run on background queues.
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
// Now we tell the ASYNCHRONOUS socket to connect.
//
// Recall that GCDAsyncSocket is ... asynchronous.
// This means when you tell the socket to connect, it will do so ... asynchronously.
// After all, do you want your main thread to block on a slow network connection?
//
// So what's with the BOOL return value, and error pointer?
// These are for early detection of obvious problems, such as:
//
// - The socket is already connected.
// - You passed in an invalid parameter.
// - The socket isn't configured properly.
//
// The error message might be something like "Attempting to connect without a delegate. Set a delegate first."
//
// When the asynchronous sockets connects, it will invoke the socket:didConnectToHost:port: delegate method.
NSError *error = nil;
#if USE_SECURE_CONNECTION
uint16_t port = 443; // HTTPS
#else
uint16_t port = 8080; // HTTP
#endif
DDLogVerbose(#"port: %d\t host: %#",port,#"130.85.92.12");
if (![asyncSocket connectToHost:#"130.85.92.12" onPort:port error:&error])
{
DDLogError(#"Unable to connect to due to invalid configuration: %#", error);
}
else
{
DDLogVerbose(#"Connecting...");
}
#if USE_SECURE_CONNECTION
// The connect method above is asynchronous.
// At this point, the connection has been initiated, but hasn't completed.
// When the connection is establish, our socket:didConnectToHost:port: delegate method will be invoked.
//
// Now, for a secure connection we have to connect to the HTTPS server running on port 443.
// The SSL/TLS protocol runs atop TCP, so after the connection is established we want to start the TLS handshake.
//
// We already know this is what we want to do.
// Wouldn't it be convenient if we could tell the socket to queue the security upgrade now instead of waiting?
// Well in fact you can! This is part of the queued architecture of AsyncSocket.
//
// After the connection has been established, AsyncSocket will look in it's queue for the next task.
// There it will find, dequeue and execute our request to start the TLS security protocol.
//
// The options passed to the startTLS method are fully documented in the GCDAsyncSocket header file.
// The deusty server only has a development (self-signed) X.509 certificate.
// So we tell it not to attempt to validate the cert (cause if it did it would fail).
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
[asyncSocket startTLS:options];
#endif
}
return self;
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
DDLogVerbose(#"socket:didConnectToHost:%# port:%hu", host, port);
// HTTP is a really simple protocol.
//
// If you don't already know all about it, this is one of the best resources I know (short and sweet):
// http://www.jmarshall.com/easy/http/
//
// We're just going to tell the server to send us the metadata (essentially) about a particular resource.
// The server will send an http response, and then immediately close the connection.
NSString *msg = #"iOS client connected\r\n\r\n";
NSData *msgdata = [msg dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:msgdata withTimeout:-1.0 tag:0];
// Side Note:
//
// The AsyncSocket family supports queued reads and writes.
//
// This means that you don't have to wait for the socket to connect before issuing your read or write commands.
// If you do so before the socket is connected, it will simply queue the requests,
// and process them after the socket is connected.
// Also, you can issue multiple write commands (or read commands) at a time.
// You don't have to wait for one write operation to complete before sending another write command.
//
// The whole point is to make YOUR code easier to write, easier to read, and easier to maintain.
// Do networking stuff when it is easiest for you, or when it makes the most sense for you.
// AsyncSocket adapts to your schedule, not the other way around.
#if READ_HEADER_LINE_BY_LINE
// Now we tell the socket to read the first line of the http response header.
// As per the http protocol, we know each header line is terminated with a CRLF (carriage return, line feed).
[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
#else
// Now we tell the socket to read the full header for the http response.
// As per the http protocol, we know the header is terminated with two CRLF's (carriage return, line feed).
[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
#endif
}
- (void)socketDidSecure:(GCDAsyncSocket *)sock
{
// This method will be called if USE_SECURE_CONNECTION is set
DDLogVerbose(#"socketDidSecure:");
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
DDLogVerbose(#"socket:didWriteDataWithTag:");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
DDLogVerbose(#"socket:didReadData:withTag:");
NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",httpResponse);
#if READ_HEADER_LINE_BY_LINE
DDLogInfo(#"Line httpResponse: %#", httpResponse);
// As per the http protocol, we know the header is terminated with two CRLF's.
// In other words, an empty line.
if ([data length] == 2) // 2 bytes = CRLF
{
DDLogInfo(#"<done>");
}
else
{
// Read the next line of the header
[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
}
#else
DDLogInfo(#"Full httpResponse: %#", httpResponse);
#endif
[httpResponse release];
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
// Since we requested HTTP/1.0, we expect the server to close the connection as soon as it has sent the response.
DDLogVerbose(#"socketDidDisconnect:withError: \"%#\"", err);
}
I've looked around for answers but have had no success. I figured the best course of action would be to ask you all rather than wrack my brain trying to solve it myself.
The solution was to connect to the local network differently. I was operating with a network that required a log in for local access but offered a "visitors" connection for wide area network access. The device (iPad) was automatically connecting as a "visitor" and I needed to log in manually.
So, if you aren't able to connect w/ this API, check out how your connecting to the network!

Resources