Xamarin.ios Web Socket with Rails cable

xamarin-io-with-web-socket

What is web socket?

Web socket is a communication protocol . It’s bit different TCP protocol from HTTP/HTTPS. Both protocols are located at layer 7. Web sockets are work over http ports 80 and 443 as well as to support http proxies and intermediaries.

Web socket, protocol specification defines is “ws” and when it secure, it will be “wss”

What is Rails cable?

Action Cable seamlessly integrates WebSockets with the rest of your Rails application. It allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being performant and scalable. It’s a full-stack offering that provides both a client-side JavaScript framework and a server-side Ruby framework. You have access to your full domain model written with Active Record or your ORM of choice.

Lets get ready backend (rails cable) for web socket.

You need to create new rails application first. Assume all the ruby and rails environment is ready. Go to Terminal and run following code.

rails new websocket

Connection with backend.

The connection will handle the relationships between client side and backend. Normally every Websocket appeared by the server. The connection will not handle any authentication and authorization. The client of a WebSocket connection is called the connection consumer. An individual user will create one consumer-connection pair per browser tab, window, or device they have open.

You will see the following folders in your rails application that related to the cable.

Screen Shot 2018-03-28 at 12.51.15 PM

You can see two files inside the applcation_cable folder. Lets see the connection.rb

The connection class inherit from “ActionCable::Connection” . In this class we can authorize the connection and process to establish if user is authorized.

See the following code.

identified_by is a connection identifier that can be used to find the specific connection later

Channels
You can see two files inside the applcation_cable folder. Lets see the channel.rb
The channel class inherit from “ActionCable::Channel”. We need to create our own channels with creating channel classes. lets try create one channel saying ChatsChannel.

These own channels need to place in side the app/channels folder.

Subscriptions.
Channels connections are called a subscriptions. Before we send and receive messages using client side, we need to subscribe.

see the code

class ChatsChannel < ApplicationCable::Channel

    def subscribed
        stream_from "chat"
    end
end

The subscribed method will call when the consent has successfully become a subscriber of this channel.

Why we adding “stream_from “chat” ” code. Because we need to start channel.

Before start server, few things need to setup.
1. Add route for the channel
2. Add configuration for the action cable

Let’s do that.
Open the route and add following code lines.

Rails.application.routes.draw do

  mount ActionCable.server => '/cable'

end

Since we are working on dev environment, go to development environment file and add following two line for that. Environment file path is Config >environments > development.rb

  config.action_cable.url = 'ws://192.168.8.104:3000/cable'
  config.action_cable.allowed_request_origins = [ 'ws://192.168.8.104:3000','http://192.168.8.104:3000' ]

Note : since location lost doesn’t support for iphone simulator we are adding ip address for request origins.

Now Many things are ready from the backend-side. use following code to run rails server.

  rails s -b 192.168.8.104

Okay Now time is for the front end development.

Xamarin.ios
First of all you need to create new xamarin product.

File -> New Solution -> Select Ios from left side -> SingleView app

In next form, enter the name organization identifier

Screen Shot 2018-03-28 at 1.45.26 PM

Give the location for the solution and Done.

First Select iOS folder from solution file list.
We’ll use the WebSocket4Net NuGet package in our mobile apps to communicate with the server.

Screen Shot 2018-03-28 at 3.27.51 PM

Open the ViewController.cs file Need to add following code lines on that class.

using System;
using WebSocket4Net;

using UIKit;

namespace SocketApp
{
    public partial class ViewController : UIViewController
    {
        WebSocket websocket = new WebSocket("ws://192.168.8.104:3000/cable");

        protected ViewController(IntPtr handle) : base(handle)
        {
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
        }
    }
}

As above code, you need to create WebSocket object with websocket url.

Note : rails development default port is 3000 and we started server using the given ip.

Now we need to write a handle for the websocket events. We have to add that for the ViewDidLoad() method. See the method body.

public override void ViewDidLoad()
{
      websocket.Opened += new EventHandler(websocket_Opened);
      websocket.Error += new EventHandler<ErrorEventArgs>(websocket_Error);
      websocket.Closed += new EventHandler(websocket_Closed);
      websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
     
      base.ViewDidLoad();
}

See the method implementation for the events.

private void websocket_Error(object sender, ErrorEventArgs e)
{
}

private void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
}

private void websocket_Closed(object sender, EventArgs e)
{
}

private void websocket_Opened(object sender, EventArgs e)
{
}

Let’s see the events
1.When socket is open “websocket_Opened” method will trigger.
2.When socket is closed “websocket_Closed” method will trigger.
3.When socket fail with some error “websocket_Error” method will trigger.
4.when get the message via socket “websocket_MessageReceived” method will trigger.

Now lets add method body for socket events.

After web socket connection is open we need to subscribe. subscribe method will not call automatically. we have to subscribe for the channel. See the below code.

private void websocket_Opened(object sender, EventArgs e)
{
      Dictionary<string, string> dictionary =
           new Dictionary<string, string>();
      dictionary.Add("command", "subscribe");
      dictionary.Add("identifier", "{"channel": "UsersChannel"}");

      var j = JsonConvert.SerializeObject(dictionary);
      websocket.Send(j);  
}

In this time I introduce JSON library as well. Add the “Newtonsoft.Json” package for the project.

Run the simulator and notice the response you are getting for “websocket_MessageReceived“. For the demo purpose will show the response.

Add the UITextView, UITextField and UIButton for the view and create outlets for that.(The sample code will be linked to the bottom of the page)

Lets add the body for “websocket_MessageReceived“.

private void websocket_Opened(object sender, EventArgs e)
{
        JObject o = JObject.Parse(e.Message.ToString());
       
        if (o["type"] == null) {
            InvokeOnMainThread(() =>
            {
                 textView.Text = textView.Text + "\n" + e.Message;
            });
        }    
}

Now all the response we are displaying on the textView excluding ping message. These thing handle on the background thread so we need to get application into main thread since we need to update UIs.

Now we have to send the message to socket. To do that we have to use button action and textfield text will send to the rails back-end via the socket.

partial void tapMessage(UIButton sender)
{
      Dictionary<string, string> dictionary =
               new Dictionary<string, string>();
      dictionary.Add("command", "message");
      dictionary.Add("identifier", "{"channel": "UsersChannel"}");
      dictionary.Add("data", "{"action":"chat_message","msg": " + """ + message.Text + ""}");

      var j = JsonConvert.SerializeObject(dictionary);
      websocket.Send(j);
}

when you see the above code you will notice, new json key added as “data”. Will check more details about that. Now we have to send the message to channel. Fo that we need to use new key and need to mention rails method on the channel. We have to use “action” as the key for set the rails action and many keys as you wish for that.

We have change the rails channel code as well. see the channel action to read it.

class ChatsChannel < ApplicationCable::Channel

    def subscribed
        stream_from "chat"
    end

    def chat_message(data)
        ActionCable.server.broadcast "chat" , success: 'yes', msg: data['msg']
    end

end

chat_message(data)” method handing the part and rending back to all the members of chat channel.

That’s it. Run on the simulator and rails server and check the textViews text. All the response will apend to the textView. You can run many simulators as you wish.

We will check android development with same rails cable socket in next Tutorials.

Source Code :
https://github.com/isamankumara/websocket-xamarin-io-with-rails
https://github.com/isamankumara/rails-action-cable
Video :

Reference :

https://en.wikipedia.org/wiki/WebSocket
http://guides.rubyonrails.org/action_cable_overview.html

Write a Reply or Comment

Your email address will not be published.