Connecting to MQTT happens after publish due to async - ios

I'm using CocoaMQTT to connect and publish events. To publish, its important that I am connected to MQTT. But connect is async and so is publish. I want it to be sequential that first it should connect and once connected then publish so for example if the connect happens after 5mins then publish should happen after that.
https://github.com/emqtt/CocoaMQTT
How exactly can I do that?
Here is my code:
class ViewController: UIViewController {
var iot: MQTTDelegate!
#IBAction func click(_ sender: Any) {
self.iot = IoT(
withClientId: "clientId",
host: "host",
port: 1883
)
iot.connect(username: "username", password: "token")
iot.publish(topic: "hello", message: "")
}
}
If I move connect to a separate button then it works as first I click the connect button and then I click the "click" button so its sequential. How do I make the above code sequential?
I used PromiseKit to promisify the code but I dont know what exactly to fulfill to connect.

It looks like you are trying to establish a connection to an MQTT server and publish a message to a topic, but the connection is being established after the message is published due to asynchronous behavior.
To fix this issue, you can use the connect() method of the MQTTClient class to establish the connection before publishing the message. The connect() method takes a completion block that is called when the connection is established or if an error occurs.
Here is an example of how you could modify your code to establish the connection before publishing the message:
client.connect { error in
if error == nil {
// Connection was successful
client.publish("topic", withString: "Hello, World!")
} else {
// There was an error connecting to the MQTT server
}
}
This way, the connection to the MQTT server will be established before the message is published, and the message will be sent as soon as the connection is ready.

Related

Socket.io swift client disconnects automatically

I am using socket.io swift client in my app (version 13.1.0) Things work fine, but sometimes this scenario occurs:
Socket gets disconnected (3 out of 10 times). After it gets disconnected it tries and gets connected successfully, but after this it gets disconnected again and this forms an infinite loop of connected - disconnected state. I am searched but didn't get any possible solution.
My code is very simple. I have created a singleton class and its code is given as follows:
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
let manager = SocketManager(socketURL: URL(string: "URL")!, config: [.compress, .log(true), .reconnects(false)])
override init() {
super.init()
let socket = manager.defaultSocket
socket.on("connect") {data, ack in
NSLog("*************** SOCKET CONNECTED")
}
}
func establishConnection() {
let socket = manager.defaultSocket
socket.connect()
}
}
Other than this I am elegantly disconnecting socket when app goes in background and then connecting it again when app comes in foreground.
Things I have tried:
Tried the configs parameters: forceNew(true/false), reconnects(true/false), forceWebsockets(true/false)
In order to keep the connection active, I am sending an empty parameter to the server every 10 seconds, so that it knows that the app is in active state.
My observation:
I am using Alamofire in the same project and it send requests in background thread. Might be possible that at some point of time both libs start using the same background thread and socket connection breaks.
Is this possible? Correct me if I am wrong in my understanding.
What should I do to overcome this socket disconnection problem. I am a newbie to iOS so any help would be appreciated.

Swift Socket.io the event sent right after connection is not executed

So I am trying to send (emit) an event right after the connection.
I am building a chat app, and the only issue I have is that when the user disconnected and connect to the server again, other clients are not informed the reconnected client is back (I think it is because my userlist data at the server end is not updated when the reconnected client is back) So I'm trying to send an event right after the connection to update the userlist data at the server end. But seems like the event is not executed for some reason. Any help would be great!
func establishConnection() {
socket.connect()
if UsersViewController.nickname != nil {
socket.emit("connectWithNewId", UsersViewController.nickname)
}
}
I have check already that the event can be send from the other place of the code. It just seems not working right after the connection.
You should emit the event when the connection is established, try something like this:
func establishConnection() {
socket.on("connect") { data, ack in
if UsersViewController.nickname != nil {
socket.emit("connectWithNewId", UsersViewController.nickname)
}
}
socket.connect()
}

How can I wait for Socket.IO to have a socket connection established before connecting a user to the server?

I'm running SocketIO-Client-Swift in order to open WebSockets and communicate with a server. However the problem I'm having is that I want to connect to the socket and then connect to the server with an emit.
SocketIOManager.sharedInstance.connectToSocket()
SocketIOManager.sharedInstance.connectToServer(self.myUsername)
And those point to functions here:
func connectToSocket() {
addHandlers()
socket.joinNamespace("/chat")
socket.connect()
}
func addHandlers() {
self.socket.on("connectUser") { data in
print("socket connected")
}
}
func connectToServer(username: String) {
socket.emit("connectUser", username)
}
Even after registering the handle, the emit is being called before the socket is properly connected. The connect works fine after the connect has been established as I can properly send messages and get feedback after my Log shows a connection.
You need to wait for the client to receive the connect event. That will signal that it is now connected and you can safely send initial data on the connection from that event handler.

Socket.io does not close the socket on demand (and does not allow my swift app to reconnect again to the node.js server)

I am playing around with socket.io library, I already implemented the server side (in node.js). I try to follow a very simple scenario:
1) user establishes connection
2) user connects to the room
3) user disconnects
4) user reconnects
I'm using ios app (written in swift) on a client side.
My server code is as follows:
io.on('connection', function(clientSocket){
console.log('a user connected here');
clientSocket.on('disconnect', function(){
console.log('user disconnected');
});
clientSocket.on('connectUser', function(username){
clientSocket.join(username);
console.log('user ' + username + ' connected to the room.');
});
Now in my client side I created a class responsible for handling all socket stuff:
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
var socket: SocketIOClient = SocketIOClient(socketURL: NSURL(string: serverURL)!, options: [.ForceNew(true)])
override init() {
super.init()
}
func establishConnection() {
socket.connect()
}
func closeConnection() {
socket.disconnect()
}
func connectToServerWithNickname(nickname: String) {
print("CONNECTING TO SOCKET SERVER \(nickname)")
socket.emit("connectUser", nickname)
}
}
Now - further on - in my swift app (in applicationDidBecomeActive) I'm calling establishConnection() and then SocketIOManager.sharedInstance.connectToServerWithNickname(username).
In my server console I see:
a user connected here
user 571fc6818451630f5becda9c connected to the room.
In my appDelegate I implemented this function:
func applicationWillResignActive(application: UIApplication) {
SocketIOManager.sharedInstance.closeConnection()
print("closing sockets")
}
so now when I put my app in the background I see closing sockets and in my server console I see user disconnected.
And now to the main problem - I want to reconnect user when he comes back to the app. Therefore I implemented this method:
func applicationDidBecomeActive(application: UIApplication) {
print("application is back to life")
SocketIOManager.sharedInstance.establishConnection()
SocketIOManager.sharedInstance.connectToServerWithNickname(username)
}
But now when I wake up the app from the background, in my server console I only see a user connected here. So this message:
user 571fc6818451630f5becda9c connected to the room.
is missing and I assume it's because my app is not reconnecting to the socket.
Now from what I've read, socket.io is really buggy and people recommend switching to other libraries, but I would like to use it anyway. I found this issue on github https://github.com/socketio/socket.io-client/issues/251 and they recommend to use a specific parameter on client side. Following this plugin's page for swift https://github.com/nuclearace/Socket.IO-Client-Swift I found the specific flag:
case ForceNew(Bool) // Will a create a new engine for each connect. Useful if you find a bug in the engine related to reconnects
and that is why I'm constructing my socket on client side as:
var socket: SocketIOClient = SocketIOClient(socketURL: NSURL(string: serverURL)!, options: [.ForceNew(true)])
but yeah, even in the official code of the Socket.IO-Client-Swift library there's a comment above the disconnect method:
/// Disconnects the socket. Only reconnect the same socket if you know what you're doing.
/// Will turn off automatic reconnects.
public func disconnect() {
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
reconnects = false
didDisconnect("Disconnect")
}
Does anyone know how could I handle that? I want to close the socket each time my app goes to the background and connect to it again when my app goes to the foreground. Thanks!
add your code in applicationWillEnterForeground
SocketIOManager.sharedInstance.establishConnection()
SocketIOManager.sharedInstance.connectToServerWithNickname(username)

Unable to connect to Apple server for Push Notification

Now i am connecting to apple server to generate push notification. but when i try to connect to apple server using tcpclient it generate an exception of unable to connect and i also ping the server using cmd ping and telnet command and i found that it not allow to communication.
this is my code snippet
private void Connect(string host, int port, X509CertificateCollection certificates)
{
Logger.Info("Connecting to apple server.");
try
{
_apnsClient = new TcpClient(host, port);
// _apnsClient.Connect(host, port);
}
catch (SocketException ex)
{
Logger.Error("An error occurred while connecting to APNS servers - " + ex.Message);
}
var sslOpened = OpenSslStream(host, certificates);
if (sslOpened)
{
_conected = true;
Logger.Info("Conected.");
}
}
this is the host "gateway.sandbox.push.apple.com" i also try the producation host but same exception occured. and using Port "2195"
it generate the following Exception :
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 17.172.232.46:2195"
Fix this issue changing the X509Certificate to X509Certificate2 and also its Collection to X509Certificate2Collection and allow the setting from firewall.

Resources