B4i Library Socket.IO Client Library

Here is the Socket.IO Client library wrap for this Github Project.
Click here for the B4A wrapper

iSocketIOClient
Author:
@Biswajit
Version: 1.4
Dependency: iRandomAccessFile
  • iSocketIOClient
    SocketIOClient library wrapper for b4i.
    • Events:
      • Ack (data As String)
      • CustomUserEvents (data As List, ack As Object)
      • OnConnect (data As List)
      • OnConnecting (data As List)
      • OnDisconnect (data As List)
      • OnError (data As List)
      • OnReconnectAttempt (data As List)
      • OnReconnecting (data As List)
    • Functions:
      • AddListener (forEvent As String, callbackSub As String) As String
        Add custom event listener. It will return an UUID. Use that UUID to remove this particular listener.
        <b>Example:</b> <code>socket.AddListener("serverevent","appevent")</code>
      • Connect (host As String, namespace As String, params As Map, secure As Boolean, server_version As Int)
        Connect SocketIO to the server
        For default namespace pass null
        Pass server_version 2 if you use socket.io v2 on the server. For socket.io v3 or later send 3
        <b>Example:</b> <code>socket.connect("http://172.0.0.1:999/",null,null,false)</code>
        Other parameters will have default value as followings:
        <b>reconnection</b> = True
        <b>reconnectionAttempts</b> = Infinite
        <b>reconnectionDelay</b> = 1
        <b>reconnectionDelayMax</b> = 10
        <b>timeout</b> = 30
      • ConnectWithOptions (host As String, namespace As String, params As Map, secure As Boolean, reconnection As Boolean, reconnectionAttempts As Int, reconnectionDelay As Int, reconnectionDelayMax As Int, timeout As Int, server_version As Int)
        Connect SocketIO to the server with custom options
        For default namespace pass null
        Pass server_version 2 if you use socket.io v2 on the server. For socket.io v3 or later send 3
        <b>Example:</b> <code>socket.connect("http://172.0.0.1:999/",null,CreateMap("test":"data"),false, true, 5,1,10,30) </code>
      • DebugLog (enable As Boolean)
        Turn on debug log. Must be called before connecting. If you are already connected call disconnect then connect again.
      • Disconnect
        Disconnect SocketIO
        On successful disconnection it will raise 'OnDisconnect' event
      • EmitBinary (event As String, data As Object)
        Same as EmitString but used to send object. Usually used to forward an object to another device.
        <b>NOTE:</b> Internally it use the B4XSerializor to serialize the object.
        <b>Example:</b> <code>socket.EmitBinary("serverevent",anyObject)</code>
      • EmitString (event As String, data As Object)
        Sends a message to the server, requesting an ack.
        <b>NOTE:</b> It is upto the server send an ack back, just calling this method does not mean the server will acknowledge.
        <b>Example:</b> <code>socket.EmitString("serverevent","something")</code>
        <b>Getting Acknowledgment from server</b><code>
        Sub serverevent_Ack(data As String)
        Log(data)
        End Sub</code>
      • Initialize (EventName As String)
        Initializes the Socket.io object
      • IsInitialized As Boolean
        Tests whether this object was initialized.
      • RemoveAllListener (forEvent As String)
        Remove all event listeners for given eventname
        <b>Example:</b> <code>socket.RemoveAllListener("serverevent")</code>
      • RemoveListener (listenerUUID As String)
        Remove a particular event listener
        <b>Example:</b> <code>socket.RemoveListener("uuid_received_from_AddListener")</code>
      • SendAck (ack As Object, data As String)
        Call to acknowledge receiving an event.

Installation:
  1. Copy XML file to B4I additional library folder.
  2. Copy .framework, .h and .a files to Libs folder of the local build server
Example Attached.
For the server code you can check Socket.IO Github example or you can use this following chat server example (written in javascript) [attached]:

JavaScript:
const express = require("express");
const app = express();
const { createServer } = require("http");
const { Server } = require("socket.io");
var users = {};

// *** FOR SECURE CONNECTION *** //

// const fs = require('fs');
// var options = {
//   key: fs.readFileSync('./key.pem'),
//   cert: fs.readFileSync('./cert.pem'),
//   passphrase: "password of cert/key file"
// };

// const httpServer = createServer(options, app);

// *** FOR NON-SECURE CONNECTION *** //
const httpServer = createServer(app);

const io = new Server(httpServer,{allowEIO3: true});

io.on("connection", (socket) => {
    console.log("User Connected.");

    socket.on('user_msg', function(data,callback){
        io.emit('new_message', data);
        callback("Data Received");
    });

    socket.on('disconnect', function(data){
        console.log('User disconnected. Reason: ' + data);
    });

    socket.on('error',function(er){
        console.log(er);
    });
});

httpServer.listen(5555, function(){
  console.log('listening on *:5555');
});

To run this example server code:
  1. Download NodeJS.
  2. Install it.
  3. Download library zip file and extract.
  4. Run cmd inside server folder
  5. Run npm install
  6. It will take some time to complete.
  7. After that run node app.js
  8. It will show listening on *:5555
  9. Now create you app and connect.
  10. That's it!
Update v1.01:
  1. Added ConnectParams method for sending additional GET parameters.
Update v1.30:
  1. Completely rewritten from scratch (though the methods are almost the same)
  2. Support binary transfer.
    1. Any object you send from B4I will only be accessible from B4I directly.
    2. For B4A, use B4XSerializer in B4A to convert the received object buffer to object.
    3. You cannot access the object from the server.
  3. Add multiple listeners to a particular event
  4. Remove all listeners for a particular event or one by one
  5. Now you can send multiple parameters from the server and receive them as a list.
Update v1.40:
  1. Based on the latest working version.
  2. Connection methods' signatures have been changed. Check above.
  3. This version is compatible with Socket.io server v2, v3, v4.
  4. Now you have to pass the server version while connecting to the server.
    1. For v2.x.x pass 2
    2. For v3.x.x and later pass 3
  5. Socket.io server v1 is no longer supported. Those who want to use v1 download the older wrapper and frameworks.
  6. Consider this as the last update because Objective-C is no longer supported.
Download all the files from here

Download previous version from here
 

Attachments

  • socket.io v1.40 example.zip
    3.3 KB · Views: 26
Last edited:

Biswajit

Active Member
Licensed User
Longtime User
Hi,
Not completed?
I'm working on it and will post it when it's done. As this library was posted for all the members I have to check the android version also else the connection between both wrappers will not work when upgrading the ios version. This whole process takes time.

I am not a full-time B4X library developer. I do this in my free time. If you have a deadline you can dm me or post it on the job offer forum and I will prioritize the task.
 

Biswajit

Active Member
Licensed User
Longtime User
Update v1.40:
  1. Based on the latest working version.
  2. Connection methods' signatures have been changed. Check above.
  3. This version is compatible with Socket.io server v2, v3, v4.
  4. Now you have to pass the server version while connecting to the server.
    1. For v2.x.x pass 2
    2. For v3.x.x and later pass 3
  5. Socket.io server v1 is no longer supported. Those who want to use v1 download the older wrapper and frameworks.
  6. Consider this as the last update because Objective-C is no longer supported.
 

mehdipass

Active Member
Update v1.40:
  1. Based on the latest working version.
  2. Connection methods' signatures have been changed. Check above.
  3. This version is compatible with Socket.io server v2, v3, v4.
  4. Now you have to pass the server version while connecting to the server.
    1. For v2.x.x pass 2
    2. For v3.x.x and later pass 3
  5. Socket.io server v1 is no longer supported. Those who want to use v1 download the older wrapper and frameworks.
  6. Consider this as the last update because Objective-C is no longer supported.
Hi
When I use "EmitString" it gives the following error:
Error:
-[__NSCFNumber bytes]: unrecognized selector sent to instance 0x92d379ca88f8548a
 

Biswajit

Active Member
Licensed User
Longtime User
Hi
When I use "EmitString" it gives the following error:
Error:
-[__NSCFNumber bytes]: unrecognized selector sent to instance 0x92d379ca88f8548a
When you post an issue you have to post the relevant code also just by seeing this error log no one can guess what is the error.
 
Last edited:

mehdipass

Active Member
When you post an issue you have to post the relevant code also just by seeing this error log no one can guess what is the error.
Hi,
This log Socket:
Log:
LOG SocketIOClient{/}: Emitting: 20["joinRoom","12445"], Ack: false
LOG OnAckCallback: OnAckCallback for 0 being released
LOG SocketEngine: Writing poll: 20["joinRoom","12445"] has data: false
LOG SocketEnginePolling: Sending poll: 20["joinRoom","12445"] as type: 4
LOG SocketEnginePolling: Got polling response
LOG SocketEnginePolling: Got poll message: 2:40
LOG SocketEngine: Got message: 40
LOG SocketParser: Parsing 0
LOG SocketEnginePolling: Doing polling GET http://.../socket.io/?transport=polling&b64=1&EIO=3&sid=ocgvVOa95zRhZtcHAK7H
LOG SocketParser: Decoded packet as: SocketPacket {type: 0; data: []; id: -1; placeholders: 0; nsp: /}
LOG SocketIOClient{/}: Handling event: websocketUpgrade with data: [["sec-websocket-accept": "vSA3jXOEnqWOMFQZHYaAeV489mg=", "upgrade": "websocket", "connection": "Upgrade"]]
LOG SocketEngineWebSocket: Sending ws: probe as type: 2
LOG SocketEnginePolling: Created POST string: 23:420["joinRoom","12445"]
LOG SocketEnginePolling: POSTing
LOG SocketEnginePolling: Doing polling POST http://.../socket.io/?transport=polling&b64=1&EIO=3&sid=ocgvVOa95zRhZtcHAK7H
LOG SocketEnginePolling: Got polling response
LOG SocketEnginePolling: Got poll message: 1:3
LOG SocketEngine: Got message: 3
LOG SocketIOClient{/}: Handling event: pong with data: []
LOG SocketEnginePolling: Doing polling GET http://.../socket.io/?transport=polling&b64=1&EIO=3&sid=ocgvVOa95zRhZtcHAK7H
LOG SocketEngine: Got message: 3probe
LOG SocketEngine: Received probe response, should upgrade to WebSockets
LOG SocketEngine: Upgrading transport to WebSockets
LOG SocketEnginePolling: Sending poll:  as type: 6
LOG SocketIOClient{/}: Handling event: pong with data: []
LOG SocketEnginePolling: Got polling response
LOG SocketEnginePolling: Got poll message: 16:42["joinRoom",1]
LOG SocketEngine: Got message: 42["joinRoom",1]
LOG SocketEngine: Switching to WebSockets
LOG SocketParser: Parsing 2["joinRoom",1]
LOG SocketEngineWebSocket: Sending ws:  as type: 5
LOG SocketEngine: Flushing probe wait
LOG SocketParser: Decoded packet as: SocketPacket {type: 2; data: [joinRoom, 1]; id: -1; placeholders: -1; nsp: /}
LOG SocketIOClient{/}: Handling event: joinRoom with data: [1]

And this error:
Error:
-[__NSCFNumber bytes]: unrecognized selector sent to instance 0xbdd5bd32aee97731
Stack Trace: (
  CoreFoundation       E2F84645-2905-31EF-8EC7-3CC19C3CDDB3 + 626960
  libobjc.A.dylib      objc_exception_throw + 60
  CoreFoundation       E2F84645-2905-31EF-8EC7-3CC19C3CDDB3 + 1532100
  CoreFoundation       E2F84645-2905-31EF-8EC7-3CC19C3CDDB3 + 189732
  CoreFoundation       _CF_forwarding_prep_0 + 96
  Hanta                -[B4IArray setBytesData:] + 92
  Hanta                -[B4INativeObject NSDataToArray:] + 116
  Hanta                __32-[iSocketIOClient AddListener::]_block_invoke + 356
  SocketIO             $sSo7NSArrayC8SocketIO0B10AckEmitterCIeyByy_SayypGAEIeggg_TRTA + 64
  SocketIO             $s8SocketIO0A8IOClientC11handleEvent_4data17isInternalMessage7withAckySS_SayypGSbSitF + 700
 SocketIO             $s8SocketIO0A8IOClientC12handlePacketyyAA0aE0VF + 228
 SocketIO             $s8SocketIO0A7ManagerC18parseEngineMessageyySSFyycfU_ + 416
 SocketIO             $sIeg_IeyB_TR + 20
 libdispatch.dylib    BD02A625-8475-3FD6-8DC3-8AED25D1573B + 10532
 libdispatch.dylib    BD02A625-8475-3FD6-8DC3-8AED25D1573B + 18032
 libdispatch.dylib    _dispatch_main_queue_callback_4CF + 944
 CoreFoundation       E2F84645-2905-31EF-8EC7-3CC19C3CDDB3 + 335236
 CoreFoundation       E2F84645-2905-31EF-8EC7-3CC19C3CDDB3 + 48988
 CoreFoundation       CFRunLoopRunSpecific + 600
 GraphicsServices     GSEventRunModal + 164
 UIKitCore            920A0EE6-D266-3058-8144-27A27B23AD62 + 5346768
 UIKitCore            UIApplicationMain + 364
 Hanta                main + 104
 dyld                 start + 520
)
SignalHandler 6
 

Biswajit

Active Member
Licensed User
Longtime User
Hanta -[B4IArray setBytesData:] + 92
Hanta -[B4INativeObject NSDataToArray:] + 116
Hanta __32-[iSocketIOClient AddListener::]_block_invoke + 356
As per these three lines, the error is occurring from the B4XSerializor that I used internally to convert list, map, array object to byte. Also, the issue is not coming from the EmitString. It's coming from the AddListener function.

Can you post the block_invoke sub code and what type of data you are sending from the server to this listener? If you don't want to post publicly you can dm me.
 

mehdipass

Active Member
Hi,
First i added this line:
AddListener:
socket.AddListener("joinRoom","joinRoom")
And next:
EmitString:
socket.EmitString("joinRoom","123456")
In b4a i use this line to get data: (also i cpoy this line in b4i)
joinroom:
Private Sub socket_joinroom(txt As String)
    Try
        Log("joinRoom: " & txt)
    Catch
        Log(LastException)
    End Try
End Sub
 

Biswajit

Active Member
Licensed User
Longtime User
Private Sub socket_joinroom(txt As String)
the method signature is wrong. The parameter should be a list not string. check the first post or the example project
 
Top