Kotak websocket uses Socket.IO server

Socket.io is a multi chat/bi-directional communication system built on the top of raw websockets (it's also supports HTTP long-polling).

Python and Js clients are available for socket.io, but neither DotNet client nor any getting started article available for DotNet!?.

If you try send message to socket.io server from any .Net websocket clients, mostly you won't get any response.

This is because the socket.io server expects messages to be sent in certain format (socket.io protocol). Check this below link for socket.io protocol.

https://github.com/socketio/socket.io-protocol

Kotak's offcial documentaion has example in Js which uses socket.io, so anyone trying to connect using raw websocket client might have failed to make it work.

Check the Kotak's js websocket documentation here.

https://tradeapi.kotaksecurities.com/devportal/apis/a38b95f8-c52e-4037-a8d0-12c12e2efff7/documents/4deb9ff6-b1b1-48c1-8d60-f665b9ba5c2d

Let's get started

Connection:

Js Example:

<script>
const socket = io("https://wstreamer.kotaksecurities.com?access_token=a38b95f878c52eer4037ioa8d0456l12c12e2efff7", { path: "/feed/", transports: ['websocket', 'polling'] });
</script>

Raw Websocket:
Here the path argument has to be included in the Url

websocket = new Websocket("wss://wstreamer.kotaksecurities.com/feed/?EIO=3&transport=websocket&access_token=a38b95f878c52eer4037ioa8d0456l12c12e2efff7")

*EIO=3 is the socket.io engine version used in Kotak server
*Also note the url scheme in Js (https://) and in raw socket (wss://)

Subscribe for Quotes:

Js Example:

<script>
socket.emit('pageload', "{'inputtoken', 'insttoken'}");
</script>

Raw Websocket:
Here we need to send the message with prefix 42
42["pageload", {"inputtoken":"insttoken"}]

WebSocket.Send("42[" & """" & "pageload" & """" & ", {" & """" & "inputtoken" & """" & ":" & """" & insttoken & """" & "}]")

*for multiple tokens send insttoken as csv token1,token2,token3

Unsubscribe is same as above except change "pageload" to "pageunload"

Other points:

Socket.io server expects a ping message from the client every 25 seconds else, it will disconnect.

For safer side send ping every 10 secs from websocket client. The following is accepted as Ping by socket.io

WebSocket.Send("3")

There are delays in connection at sometimes that we reported to Kotak team.

You have to send message only after you receive welcome message from socket.io server.

Kotak socket sends the welcome message as "broadcast" event at sometime and "message" event at some other times.
You will be able to subscribe and receive quotes if the welcome message is sent us "message" from kotak socket.
If the welcome message is received as "broadcast", disconnect and connect gain with socket.io server.

Sample messages received from socket.io on connect

40
0{"sid":"bRapKCZCWDMNT 2_AAen","upgrades":[],"pingInterval":25000,"pingTimeout":5000}
42["broadcast", "welcome to Streamer Io (Build: 20201120).")

40
0{"sid":"_QmZIS7Diwsp459VAAEq", "upgrades":[],"pingInterval":25000,"pingTimeout":5000}
42["message","welcome to Streamer IO (Build: 20200709). ")


Full Example using Websocket4Net:

 

Module KotakSocket
    ''' 
    ''' Basic Example
    ''' Modify as required
    ''' Add error handling
    ''' 

    Private Websock As WebSocket

    Sub main()
        Dim ConsumerKey As String = "xxxxxxx"
        Dim ConsumerSecret As String = "yyyyyy"

        Dim token As String = GetTokenWebSock(ConsumerKey, ConsumerSecret)
        If Not String.IsNullOrEmpty(token) Then
            Connect(token)
            '//Start the Ping loop after successful connect
        End If

        Console.ReadKey()
    End Sub

    Private Function GetTokenWebSock(ByVal ConsumerKey As String, ByVal ConsumerSecret As String) As String
        Try
            Dim auth As String = ConsumerKey & ":" & ConsumerSecret
            Dim authBase64 As String = Convert.ToBase64String(Encoding.UTF8.GetBytes(auth))
            Dim json As String = "{" & """" & "authentication" & """" & ": " & """" & authBase64 & """" & "}"

            Using client As New WebClient
                client.Headers(HttpRequestHeader.ContentType) = "application/json"
                Dim postBytes As Byte() = Encoding.ASCII.GetBytes(json)
                Dim respBytes As Byte() = client.UploadData("https://wstreamer.kotaksecurities.com/feed/auth/token", "POST", postBytes)
                Dim respString As String = Encoding.ASCII.GetString(respBytes)
                Dim token As String '= //parse the json response with json client and extract the token
                Return token
            End Using
        Catch Ex As Exception
        End Try
        Return ""
    End Function

    Private Sub Connect(ByVal tokenWebsock As String)
        Websock = New WebSocket("wss://wstreamer.kotaksecurities.com" & "/feed/?EIO=3&transport=websocket&access_token=" & _
        tokenWebsock, "", WebSocketVersion.Rfc6455)

        Websock.Security.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12 '//Onll Tls2 supported by Kotak

        'AddHandler
        AddHandler Websock.Opened, AddressOf WebSockOpened
        AddHandler Websock.Closed, AddressOf WebSockClosed
        AddHandler Websock.MessageReceived, AddressOf WebSockMessageReceived
        AddHandler Websock.Error, AddressOf WebSockError

        Websock.Open()
    End Sub

    Private Sub WebSockOpened(sender As Object, e As System.EventArgs)
        Console.WriteLine("socket opened")
    End Sub

    Private Sub WebSockMessageReceived(sender As Object, e As WebSocket4Net.MessageReceivedEventArgs)
        Console.WriteLine("message received from socket: " & e.Message)
        '//Do data parsing here
    End Sub

    Private Sub WebSockClosed(sender As Object, e As System.EventArgs)
        Console.WriteLine("socket closed")
        '//Do retry logic here
    End Sub

    Private Sub WebSockError(sender As Object, e As SuperSocket.ClientEngine.ErrorEventArgs)
        Console.WriteLine("socket error: " & e.Exception.Message)
        '//Do retry logic here
    End Sub

    Private Sub PingWebsocket()
        Do
            Thread.Sleep(10000) 'CHECK
            If Websock Is Nothing Then Continue Do
            Websock.Send("3")
        Loop
    End Sub
End Module

References:
https://stackoverflow.com/questions/24564877/what-do-these-numbers-mean-in-socket-io-payload