2

I've been trying for a couple of days with limited success to use TCP to make two ruby programs on the same or different machines communicate.

I'm looking for example 'client' and 'server' scripts that will work straight away, once I've chosen ports that work.

Client code I found that seems to work, shown below.

But I haven't got a server working with it.

# Seems to work for some reason
require 'socket'

tcp_client=TCPSocket.new('localhost',1540)
while grab_string=tcp_client.gets
puts(grab_string)
end
tcp_client.close

I'm interested in the simplest possible solution, that works on my machine.

All it has to do is send a string. The answer I'm looking for is just like this but with ruby, instead of python.

Feel free to change the code for client and server, with only half the puzzle in place I'm not sure if its works or not.

Server code

# Server
require 'socket'

sock = TCPSocket.new('localhost', 1540)
sock.write 'GETHELLO'
puts sock.read(5) # Since the response message has 5 bytes.
sock.close

Using the code suggested by kennycoc I get the following error message

Server.rb:3:in `initialize': Only one usage of each socket address (protocol/network address/port) is normally permitted. - bind(2) for nil port 1540 (Errno::EADDRINUSE)
        from Server.rb:3:in `new'
        from Server.rb:3:in `<main>'
Adjam
  • 598
  • 1
  • 8
  • 22
  • 2
    Tip: If you're sending arbitrary files, use `read` and `write` on fixed-length chunks. `gets` is for line-based files and will act really strangely on binary data, possibly even wrecking it due to CR-LF conversion. – tadman Jun 05 '18 at 18:46
  • What have you tried? Can you show us the server program that isn't working? – Linuxios Jun 05 '18 at 18:47
  • tadman: It doesn't have to use gets, thanks for the tip! Linuxios, I'vee added my server code, but it doesn't seem to work. I'm too new to TCP to figure out without a working code example. I've tried copying different snippets of code but there doesn't seem to be a definitive stack overflow answer to this problem that works. I've got a work around using MySQL but its very cumbersome – Adjam Jun 05 '18 at 18:54

3 Answers3

3

@adjam you haven't created a TcpServer, TCPSocket is used to create TCP/IP client socket

To create TCP/IP server you have to use TCPServer

EX: Tcp/ip Server code:

require 'socket'
server = TCPServer.open(2000)
client = server.accept # Accept client
while (response = client.gets) # read data send by client
 print response
end

Tcp/ip Client code:

require 'socket'
client = TCPSocket.open('localhost', 2000)
client.puts "hello"
client.close;
rahul mishra
  • 1,390
  • 9
  • 16
2

Taking the documentation from https://ruby-doc.org/stdlib-2.5.1/libdoc/socket/rdoc/Socket.html, you seem to be looking for something like this:

require 'socket'
server = TCPServer.new(1540)
client = server.accept
client.puts "GETHELLO"
client.close
server.close

More generally, if you'd like the server accessible for multiple clients to request data from, you'd have a loop running like

loop do
  client = server.accept
  client.puts "gethello"
  client.close
end
iCodeSometime
  • 1,444
  • 15
  • 30
  • And just note that this particular example only serves one client, and then shuts down. – Linuxios Jun 05 '18 at 19:08
  • Right. It looked like that was what he was aiming for in his example. Updated to make that more clear – iCodeSometime Jun 05 '18 at 19:16
  • Oh, definitely. Just wanted that to be stated explicitly for future viewers. – Linuxios Jun 05 '18 at 19:17
  • I love the simplicity, that's how I learn best. Sadly it gives an error, I've updated the question to include command prompts error message. I hope I can get it to run, stack overflow is lacking a simple working example for Ruby – Adjam Jun 05 '18 at 19:39
  • Are you sure you don't have another socket bound to that port? If a socket is currently bound to that port you'll get that error. – iCodeSometime Jun 05 '18 at 19:43
0

tcp_server.rb

require "socket"

server = TCPServer.new(1234)

loop do  # Keep the server alive
  session = server.accept
  puts "Request arrived"
  session.write "Time is #{Time.now}" # Send data to client
  session.close
end

tcp_client.rb

require "socket"

socket = TCPSocket.open("localhost", 1234)
puts socket.gets # Print sever response
socket.close

Now - If you want two-way communication between server and client use following

tcp_client.rb

require "socket"

socket = TCPSocket.open("localhost", 1234)
socket.puts "Sample data to server" # Send data to server
puts socket.gets # Print sever response
socket.close

tcp_server.rb

require "socket"

server = TCPServer.new 1234

loop do
  session = server.accept
  puts "Data recieved - #{session.gets}" # Read data from client
  session.write "Time is #{Time.now}" # Send data to clent
  session.close
end