asyncsocket ipad doesn't connect to server [closed] - ios

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!

Related

Can you setup listener socket on localhost with iOS?

I'm trying to setup a listenerSocket on localhost using GCDAsyncSocket for iOS device.
In the socketDidDisconnect delegate I either get error Code=49 for trying with port 0 (which I'm hoping would find the first available free port).
Or if I use a port no then I get error Code=61 for trying to connect with localhost.
- (IBAction)start:(id)sender {
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if(![asyncSocket connectToHost:#"localhost" onPort:0 error:&err])
{
NSLog(#"Connect Error: %#", err);
}
}
#pragma mark – delegate
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(#"socketDidDisconnect");
if (err) {
NSLog(#"Socket Error: %#", err);
// Error in connect function:
// NSPOSIXErrorDomain Code=49 "Can't assign requested address" - onPort:0
// NSPOSIXErrorDomain Code=61 "Connection refused" - connectToHost:#"localhost"
}
}
connectToHost will act as the client-side of the connection. You want to read the Writing a server section of the help page:
listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![listenSocket acceptOnPort:port error:&error])
{
NSLog(#"I goofed: %#", error);
}
- (void)socket:(GCDAsyncSocket *)sender didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
// The "sender" parameter is the listenSocket we created.
// The "newSocket" is a new instance of GCDAsyncSocket.
// It represents the accepted incoming client connection.
// Do server stuff with newSocket...
}
However you need to know the port to use (if you let the system decide what port to use then how is a client supposed to know how to connect to the server?). Also the port will almost certainly need to be > 1024 (out of the reserved port range). However I haven't ever tried to create a Server on iOS.

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

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.

XMPPFramework - Connect via SSL on Openfire

I'm trying to connect my users via SSL from my iOS XMPP chat client to Openfire server.
In my iOS client:
- (void)setupStream
{
...
// BOOL values for security settings
customCertEvaluation = NO;
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
}
In my Openfire server's Security Settings > Client Connection Security, I've set:
Required - Clients can only connect to the server using secured connections.
Thus, the following delegate method will be called:
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
NSString *expectedCertName = [xmppStream.myJID domain];
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
if (allowSSLHostNameMismatch)
[settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];
else
if (expectedCertName)
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
I attempted this solution from this thread: XMPPFramework TLS/SSL connection with Openfire
However, when I run my application and attempt to connect to the server, I'd receive this error:
Security option unavailable - kCFStreamSSLAllowsAnyRoot - You must use manual trust evaluation
I looked through the GCDAsyncSocket class and realized kCFStreamSSLAllowsAnyRoot is stated as deprecated. An NSAssert was implemented to deliberately throw the error.
Next, I decided to change my BOOL values as such:
- (void)setupStream
{
...
// BOOL values for security settings
// Manually evaluate trust
customCertEvaluation = YES;
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
}
This time, again, no connection could be made to the server but, no error was prompted.
I could connect to Openfire fine if I changed the Client Connection Security back to the original setting > Optional. But, I wouldn't be connected via SSL as indicated by a lock icon beside every user's status in Client Sessions.
My Android client (using Smack API for XMPP) connects to Openfire via SSL without issues. So I'm wondering if there's workaround I have to implement for my iOS client using XMPPFramework.
I would greatly appreciate any advices.
Explanation
In the latest version of XMPP (after April 22), you can no longer use allowSelfSignedCertificates = YES with the following:
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];`
This is because kCFStreamSSLAllowsAnyRoot & SSLSetAllowsAnyRoot have been deprecated.
/*
* ==== The following UNAVAILABLE KEYS are: (with throw an exception)
* - kCFStreamSSLAllowsAnyRoot (UNAVAILABLE)
* You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust).
* Corresponding deprecated method: SSLSetAllowsAnyRoot
*/
See XMPPFramework/GCDAsyncSocket.h & Deprecated Secure Transport Functions.
Solution
Go to Openfire server > Security Settings > Client Connection Security
Check: Required - Clients can only connect to the server using secured connections.
Define variable in AppDelegate
BOOL customCertEvaluation;
Set variable in setupStream
- (void)setupStream
{
...
customCertEvaluation = YES;
}
Set security settings in willSecureWithSettings
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
/*
* Properly secure your connection by setting kCFStreamSSLPeerName
* to your server domain name
*/
[settings setObject:xmppStream.myJID.domain forKey:(NSString *)kCFStreamSSLPeerName];
/*
* Use manual trust evaluation
* as stated in the XMPPFramework/GCDAsyncSocket code documentation
*/
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
}
Validate peer manually
/*
* This is only called if the stream is secured with settings that include:
* - GCDAsyncSocketManuallyEvaluateTrust == YES
* That is, if a delegate implements xmppStream:willSecureWithSettings:, and plugs in that key/value pair.
*/
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
/* Custom validation for your certificate on server should be performed */
completionHandler(YES); // After this line, SSL connection will be established
}
I was having the same issue, after i updated my XMPPFramework. After days of trying to find out what went wrong i came across this question, but the solution didn't work for me.
Here is what worked for me. The problem seems to originate from your xmppStream.startTLSPolicy. Setting startTLSPolicy explicitly worked for me.
xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyPreferred; // or
xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicyRequired;
Here is an EXPLANATION of why it works.
In XMPPStream's handleStreamFeatures method, it turns out that. If your XMPP Server doesn't return starttls as 'required' and you don't set startTLSPolicy(default=XMPPStreamStartTLSPolicyAllowed) explicitly. The client will just do a normal connection and not a TLS one.
Here is section of code(for reference) in XMPPStream that is doing the checks.
/**
* This method is called anytime we receive the server's stream features.
* This method looks at the stream features, and handles any requirements so communication can continue.
**/
- (void)handleStreamFeatures
{
NSAssert(dispatch_get_specific(xmppQueueTag), #"Invoked on incorrect queue");
XMPPLogTrace();
// Extract the stream features
NSXMLElement *features = [rootElement elementForName:#"stream:features"];
// Check to see if TLS is required
// Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found)
NSXMLElement *f_starttls = [features elementForName:#"starttls" xmlns:#"urn:ietf:params:xml:ns:xmpp-tls"];
if (f_starttls)
{
if ([f_starttls elementForName:#"required"] || [self startTLSPolicy] >= XMPPStreamStartTLSPolicyPreferred)
{
// TLS is required for this connection
// Update state
state = STATE_XMPP_STARTTLS_1;
// Send the startTLS XML request
[self sendStartTLSRequest];
// We do not mark the stream as secure yet.
// We're waiting to receive the <proceed/> response from the
// server before we actually start the TLS handshake.
// We're already listening for the response...
return;
}
}
else if (![self isSecure] && [self startTLSPolicy] == XMPPStreamStartTLSPolicyRequired)
{
// We must abort the connection as the server doesn't support our requirements.
NSString *errMsg = #"The server does not support startTLS. And the startTLSPolicy is Required.";
NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
otherError = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info];
// Close the TCP connection.
[self disconnect];
// The socketDidDisconnect:withError: method will handle everything else
return;
}
// Check to see if resource binding is required
// Don't forget about that NSXMLElement bug you reported to apple (xmlns is required or element won't be found)
NSXMLElement *f_bind = [features elementForName:#"bind" xmlns:#"urn:ietf:params:xml:ns:xmpp-bind"];
if (f_bind)
{
// Start the binding process
[self startBinding];
// We're already listening for the response...
return;
}
// It looks like all has gone well, and the connection should be ready to use now
state = STATE_XMPP_CONNECTED;
if (![self isAuthenticated])
{
[self setupKeepAliveTimer];
// Notify delegates
[multicastDelegate xmppStreamDidConnect:self];
}
}
You are trying to use outdated API, check iPhoneXMPP sample for the new one - https://github.com/robbiehanson/XMPPFramework/commit/73f3c35a930b91d27e62bc19e91d9cdcc02c6e42
customCertEvaluation = YES;
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
try these this might help

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

ios Read data at fast rate in UDP

i am establishing a UDP connection using GCDAsyncSocket(ios device). Everything working fine and im able to send and receive messages, my problem is that i want to exchange data fast. I can send pretty fast data from my iphone to a pc but i cant get at that speed data from pc, more specific i want to be able to get data every 100ms.
I use this function when i connect successfully:
-(void)startRead {
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(startRead) userInfo:nil repeats:YES];
[asyncSocket readDataWithTimeout:-1 tag:0];
}
With this i can read data with 1sec interval but if i try to put 0.1 seconds my program freezes.(Same with values under 1second) Im sure that im doing something wrong here and there will be a way to achieve what i want so if anybody know plz help!!
thanx
I believe the above comment is correct, you've not set the Delegate correctly on init. The socket creation should be something like this
GCDAsyncUdpSocket* udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:0 error:&error])
{
[self logError:[NSString stringWithFormat:#"Error binding: %#", error]];
return;
}
if (![udpSocket beginReceiving:&error])
{
[self logError:[NSString stringWithFormat:#"Error receiving: %#", error]];
return;
}
NSString *_host = nil;
uint16_t _port = 0;
[GCDAsyncUdpSocket getHost:&_host port:&_port fromAddress:udpSocket.localAddress];
[self logInfo:[NSString stringWithFormat:#"Socket setup on host %#:%d", _host, _port]];
[self logInfo:#"Socket created successfully."];
Unless you're using a different version of GCDAsyncUdpSocket than I'm familiar with, the correct callback method is actually the below method. This is called automatically when the delegate is set and a packet is received on the correct port.
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext

Resources