0

I'm trying to send console commands from one machine to another using Python sockets. I want the server to send back the results of the command to the client. If the client types "ls" I want the server to send back the results of running that command. Instead of the expected result, the server just says "action completed: ls". How can I fix this so the server will run the expect commands and return the result?

Server:

import socket
from subprocess import call


def main():
     host = '127.0.0.1'
    port = 5000

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, port))

    s.listen(1)
    c, addr = s.accept()
    print('Connection established: ' + str(addr))

    while True:
        try:
            data = c.recv(1024).decode('utf-8')
            print('sending data: ' + data)
            c.send(data.encode('utf-8'))
            if data == 'q':
                break
        except NameError:
            error = 'Command does not exist'
            c.send(error.encode('utf-8'))
            continue
        except SyntaxError:
            error = 'Command does not exist'
            c.send(error.encode('utf-8'))
            continue
    c.close()

Client:

import socket
from subprocess import call


def main():
    host = '127.0.0.1'
    port = 5000

    s = socket.socket()
    s.connect((host, port))
    message = str(input('> '))
    while message != 'q':
        try:
            s.send(message.encode('utf-8'))
            data = s.recv(1024).decode('utf-8')
            print('Action completed: %s' % data)
            message = str(input('> '))
        except NameError:
            print("Command not recognized.")
            continue
        except SyntaxError:
            print("Command not recognized")
            continue
10
  • Ignore the subprocess import. That's so the client can run subprocess commands Commented Oct 4, 2018 at 18:23
  • you might look into the subprocess module, and depending on what version of python you're using, whatever arguments allow you to capture the subprocess' output (stdout=subprocess.PIPE, etc.). Commented Oct 4, 2018 at 18:23
  • 1
    You are using sockets wrongly. TCP is a stream protocol. You have to built some protocol on top of it, to get the commands correctly transmitted. Commented Oct 4, 2018 at 18:46
  • NameError and SyntaxError are programming errors, and should not handled in code. Commented Oct 4, 2018 at 18:47
  • 1
    Client side there's no reason for you to handle those errors. Just check what you received from the server and print errors based on your recv. Another thing you have to note is that s.recv(1024) isn't always going to give you the full data, so you need some sort of protocol to know the beginning and end of a command like how Daniel mentioned earlier. Lastly, if you're doing this out of learning experience, that's great. If you're trying to use this in order to do something else, I recommend using a library like Paramiko or any alternative to do ssh commands. Commented Oct 4, 2018 at 19:24

1 Answer 1

1

I recently built a socket connection in order to communicate with an android device.

I decided to use UDP instead of TCP (which is what you did). For UDP as well as TCP you need a sender and a receiver on both sides of the communication.

The port number that is received in the "addr" variable changes with every connection, so you cannot use it.

What I did, I assigned two different ports one for sending from A to B and the other port to send from B to A.

Here is my server code:

import socket                    # socket connection
import threading                 # Multithreading
import time                      # Timeing

# ----------------------------------------------
#              Variables
# ----------------------------------------------
UDPListen2Port = 12345
UDPSend2Port = 123456
Listen2IP = ''  # input your local IP here

# ----------------------------------------------
#              Threading class
# ----------------------------------------------

class signalProcessingThread(threading.Thread):
    def __init__(self, iP, cmdIn):
        threading.Thread.__init__(self)
        self.iP = iP
        self.cmdIn = cmdIn
        
    def run(self):
        print("Recv--", self.iP ,"--", self.cmdIn)  # Display Thread Info
        cmdOut = self.EvalMessage()                 # Actual signal processing
        byteOut = bytes(cmdOut.encode("utf-8"))     # Convert Server reply to bytes
        sock.sendto(byteOut,(self.iP,UDPSend2Port)) # Send Server Reply to Socket

# ----------------------------------------------
#              Initialize Socket
# ----------------------------------------------

sock = socket(AF_INET, SOCK_DGRAM)              # -- UDP -- connection
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)    # in case the port was not properly closed before
sock.bind((Listen2IP,UDPListen2Port))           # bind to the port


# ----------------------------------------------
#              Listen to Socket
# ----------------------------------------------

while True:
    try: # wait for a connection
        data,addr = sock.recvfrom(66507) # number of bytes in the message
        msg = data.decode('utf-8')
        newThread = signalProcessingThread(addr[0],msg)
        newThread.start()
        
    except KeyboardInterrupt:
        print('Connection failed')
        sock.close()
        
sock.close()

The client code is quite similar, with the difference that it doesn't necessarily need to run in a thread. Hope I could help.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.