Home > Net >  What is the equivalent of Kotlin WebSocketSession object in c#?
What is the equivalent of Kotlin WebSocketSession object in c#?

Time:09-03

For a few months now I have been using the ktor framework to create servers that expose rest calls and communication via webSockets. For now I have always used clients using kotlin as a programming language (or Android App, or App Desktop).

Specifically, I had a class that was injected with the HttpClient object (from the documentation = Asynchronous client to perform HTTP requests).

Within this class I have 4 methods:

  1. start the session: instantiate the WebSocketSession object (Represents a web socket session between two peers)
  2. send Frame
  3. receives Frame
  4. close the session

In Ktor my class is something that looks a lot like this:

class WebSocketServiceImpl(
    private val client: HttpClient
){

private var socket: WebSocketSession? = null

//1)
suspend fun initSession(username: String): Resource<Unit>{
   socket = client.webSocketSession {
                url("ws://xxx.xxx.xxx.xxx:xxxx/myRoute?username=$username")
}

//2)
suspend fun send(myObj: MyObj) {
        try {
            val myObjSerialized = Json.encodeToString(myObj)
            socket?.send(Frame.Text(myObjSerialized ))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

//3)
fun observePrintableMessages(): Flow<MyObj> {
        return try {
            socket?.incoming
                ?.receiveAsFlow()
                ?.filter { it is Frame.Text }
                ?.map {
                    val myObjString = (it as? Frame.Text)?.readText() ?: ""
                    val printableMessageDto = Json.decodeFromString<MyObj>(myObjString)
                } ?: flow { }
        } catch (e: Exception) {
            e.printStackTrace()
            flow { }
        }
    }

//4)
suspend fun closeSession() {
        socket?.close()
    }

}

From the C # documentation instead, I found these examples on how to use Client-side WebSockets:


//1)
const exampleSocket = new WebSocket("wss://www.example.com/socketserver", "protocolOne");

//2)
exampleSocket.send("Here's some text that the server is urgently awaiting!");

//3)
exampleSocket.onmessage = (event) => {
  console.log(event.data);
}

//4)
exampleSocket.close();

Admitted and not granted that the methods I found in C # really work, to make the WebSocket object used in C # be equivalent to the WebSocketSession object in Kotlin is enough for me to do so? :


public void initSession(string username)
{
   exampleSocket = new WebSocket($"wss://www.example.com/socketserver?username={username}", "");
}


Or is it some other type of object to use?

If for any reason you don't know the answer, you don't need to vote negative, you can just move on.

CodePudding user response:

I used the Websocket.Client library (by Mariusz Kotas) found on NuGet

public class WebSocketService : IWebSocketService
{

    public event EventHandler<MessageReceivedEventArgs> MessageReceived;
    private void FireMessageReceivedEvent(Message message) => MessageReceived?.Invoke(this, new MessageReceivedEventArgs(message));

    public string Url { get => "ws://192.168.1.202:8082/chat-socket"; }

    private WebsocketClient webSocketClient;


    public async Task<SessionResoult> InitSession(string username)
    {
        string usernameSession = $"?username={username}";
        string urlWithUsername = $"{Url}{usernameSession}";
        try
        {
            webSocketClient = new WebsocketClient(new Uri(urlWithUsername));
            await webSocketClient.Start();
            if (webSocketClient.IsRunning)
            {
                SubscribeNewMessages();
                return new SessionResoult.Success();
            }
            else
            {
                return new SessionResoult.Error("webSocketClient is not running");
            }
        }
        catch(Exception ex)
        {
            return new SessionResoult.Error(ex.Message);
        }
        
       
    }

    private void SubscribeNewMessages()
    {
        webSocketClient.MessageReceived.Subscribe(m =>
        {
            MessageDto message = JsonConvert.DeserializeObject<MessageDto>(m.Text);
            FireMessageReceivedEvent(message.ToMessage());
        });
    }

    public async Task SendMessageAsync(string message)
    {
        
        await Task.Run(() => webSocketClient.Send(message));
    }

    public void CloseSession()
    {
        webSocketClient.Dispose();
    }


}

In the code, the interesting parts are:

1) initialization of the WebsocketClient object

2) the subscription of receiving messages ( Start() method immediately after initialization)

3) observation of message subscription -> webSocketClient.MessageReceived.Subscribe

4) the 'Fire' of the event linked to the observation of messages -> FireMessageReceivedEvent

5) those who use the class must subscribe to the event of the latter ->

webSocketService.MessageReceived = (sender, e) => {OnMessageReceived (e.MessageReceived); };

MessageReceivedEventArgs -> Class describing the Arguments of the event

SessionResoult -> Class similar to an Enum but with the possibility of passing a string or not based on which subclass it is

  • Related