Python and Ruby socket program error with data receiving

341 views Asked by At

I am writing a program in which one script (the python script) hosts a server, and the ruby script then connects, after doing so, the python script displays a prompt and sends the data to the connected ruby client, the ruby program then executes the command via system function, my error is the command only executes when you end the connection on the server (python script) so I can send only one command, then end the connection and the ruby script then executes, I want it to run and execute the commands as it receives them. Here are the scripts:

python:

#!/usr/bin/env python
import socket
import time
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(('192.168.1.104',567))
sock.listen(1)
(client,(ip,port))=sock.accept()
print('[*] Connection from {} via port {}').format(ip,port)
while True:
    cmd = raw_input("# ")
    client.send(str(cmd))

Ruby:

class C
    attr_accessor :clr
end
    r = C.new
    r.clr = "\033[0;31m"
    d = C.new
    d.clr = "\033[0;00m"
require 'socket'
def sock_setup(address,port)
    @addr = address
    @port = port.to_i
    @socket = TCPSocket.open(@addr,port)
    while TRUE
        @cmd = @socket.read(1024)
        puts @cmd
        system(@cmd)
    end
end
print("Address=> ")
@host = $stdin.gets.chomp
print("\n")
print("Port=> ")
@port_ = $stdin.gets.chomp
sock_setup(@host,@port_)
2

There are 2 answers

0
Steffen Ullrich On

I'm no expert with Ruby but read(size) is implemented in many languages in a blocking way, i.e. it will only return once size bytes are read or the connection is closed (EOF). Looking at the documentation it seems to be the same in Ruby:

Note that this method behaves like fread() function in C. This means it retry to invoke read(2) system call to read data with the specified length (or until EOF). This behavior is preserved even if ios is non-blocking mode.

This means that it will wait in your case either that it gets 1024 bytes or that the connection gets closed. Given that the commands you send are probably less than the 1024 bytes it will thus only execute the command on connection close.

The same documentation also suggests what you should use if you don't like this behavior:

If you need the behavior like single read(2) system call, consider readpartial, #read_nonblock and sysread.

Please not also that there is no guarantee that all the data you sent at once will be received within a single sysread or similar by the peer. This might work when only sending a small amount of data but will fail with larger amounts in which case you might actually need multiple sysread to read all data. And, since TCP is a streaming protocol there is no implicit message boundary so you have to design your application protocol to properly mark the end of a message in case another message might be sent by the sender before the recipient had a chance to fully read the first one.

0
John Doe On

I was able to rectify the error by changing "read" to "gets"

@cmd = @socket.read(1024) -> @cmd = @socket.gets(1024)