Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a tcp socket in a rails app?

I'm a complete beginner to rails and web development in general. I'm looking to implement a ruby TCPSocket server in a rails application which will recieve data from the client over a raw tcp connection without the http protocol. The app will have other functionality which will be handled by rails. Is this possible? For example this is a simple server that i can run on my computer:

require 'socket'               

server = TCPServer.new 3490  
puts "waiting for connection"
client = server.accept  
puts "client found"                         
while str=client.recv(100);      
    val=str.unpack("H*")
    temp=val.join('').gsub('0','').to_i

#application specific code below
    if temp<100
        temp=temp*10
    end
    print "Temperature: "
    puts temp*0.125
 end

How can I implement this in a rails app? Any kind of suggestions would be appreciated.

like image 696
Ujan Avatar asked Aug 01 '16 15:08

Ujan


People also ask

How is TCP socket implemented?

TCP sockets are used for communication between a server and a client process. The server's code runs first, which opens a port and listens for incoming connection requests from clients. Once a client connects to the same (server) port, the client or server may send a message.

What is TCP socket in API?

A socket programming interface provides the routines required for interprocess communication between applications, either on the local system or spread in a distributed, TCP/IP based network environment. Once a peer-to-peer connection is established, a socket descriptor is used to uniquely identify the connection.


2 Answers

Rails is basically Rack application, as per Rails documentation,

Rails.application is the primary Rack application object of a Rails application. Any Rack compliant web server should be using Rails.application object to serve a Rails application.

Since Rack primarily wraps HTTP requests and responses, one may not be able to build pure TCP IP socket based interaction with Rails Server.

However, you may want to have look at Action Cable, a new addition to Rails 5 - which integrates websockets with Rails application. As per Wikipedia,

The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request.

How to extract Action Cable to work with non browser clients may be tricky given that Rails is primarily a web application framework.

like image 186
Wand Maker Avatar answered Oct 12 '22 19:10

Wand Maker


You can make the TCP Sockets in the rails application and to handle multiple request at the same time implement threading. For communication use either the text format or JSON.

link: https://ruby-doc.org/stdlib-2.4.0/libdoc/socket/rdoc/TCPServer.html

First create a task inside the lib directory by following command:

rails g task socketing start

This will create a file inside the app/lib/tasks/ with name socketing.rake and inside it a task "start" would be created. Now Edit the file as:

  task start: :environment do
    require 'socket'
    puts "Started TCP Server"
    server = TCPServer.new 53492 # Server bound to port 53492
    loop do
      Thread.start(server.accept) do |client|
        p "Inside Task"
        string = client.recv(1000).chomp ## Request Data received at the socket port
        result = JSON.parse(string)
        p 'Bye'
        client.puts result.to_s
        client.close
      end
    end
  end

From Terminal run socket from project folder as:

rails socketing:start

or run as demon with nohup

Now the application will start listening at port 53492 in TCP and start sending responses to requests.

Sample Request in JSON format:

echo '{"password" : "12345678" , "name" : "[email protected]"}' | nc localhost 53492

or create the socket using a module and require it inside the controller action in that case create a new module inside the app/lib/socketing.rb

with the following code:

require 'socket'
puts "Started TCP Server"
server = TCPServer.new 53492 # Server bound to port 53492
loop do
  Thread.start(server.accept) do |client|
    p "Inside Task"
    string = client.recv(1000).chomp ## Request Data received at the socket port
    result = JSON.parse(string)
    p 'Bye'
    client.puts result.to_s
    client.close
  end
end

and define the routing to that controller:

  get '/socket', to: 'webhook#socket', as: 'socket'

Give a call to that route from browser and the TCP server would be started and start sending the responses to the requests and you can check the logs also. enter image description here enter image description here

like image 2
vidur punj Avatar answered Oct 12 '22 19:10

vidur punj