Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python client / server question

I'm working on a bit of a project in python. I have a client and a server. The server listens for connections and once a connection is received it waits for input from the client. The idea is that the client can connect to the server and execute system commands such as ls and cat. This is my server code:

import sys, os, socket


host = ''                
port = 50105

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: ", port)

s.listen(5)
print("Server listening\n")
conn, addr = s.accept()
print 'New connection from ', addr
while (1):
    rc = conn.recv(5)
    pipe = os.popen(rc)
    rl = pipe.readlines()
    file = conn.makefile('w', 0)
    file.writelines(rl[:-1])
    file.close()
    conn.close()

And this is my client code:

import sys, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
cmd = raw_input('$ ')
s.send(cmd) 
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())

When I start the server I get the right output, saying the server is listening. But when I connect with my client and type a command the server exits with this error:

Traceback (most recent call last):
File "server.py", line 21, in <module>
  rc = conn.recv(2)
File "/usr/lib/python2.6/socket.py", line 165, in _dummy
  raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor

On the client side, I get the output of ls but the server gets screwed up.

like image 649
AustinM Avatar asked Jan 09 '11 22:01

AustinM


People also ask

How does Python connect to client server?

In the server example, .listen() enables a server to accept connections. It makes the server a “listening” socket: # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() # ... The .listen() method has a backlog parameter.

How do I connect multiple clients to one server in Python?

Connect Multiple Clients in Python We have to create a brand new function and name it multi_threaded_client() ; this connects every client from the various address provided by the server simultaneously. Within the multi_threaded_client function, the connection.

How do I create a client server in Python?

Python Socket Server To use python socket connection, we need to import socket module. Then, sequentially we need to perform some task to establish connection between server and client. We can obtain host address by using socket. gethostname() function.


2 Answers

Your code calls conn.close() and then loops back around to conn.recv(), but conn is already closed.

like image 56
Greg Hewgill Avatar answered Nov 14 '22 22:11

Greg Hewgill


If you want your client to repeat what it's doing, just add a loop in there ;)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
while True:
    cmd = raw_input('$ ')
    s.send(cmd) 
    file = s.makefile('r', 0)
    sys.stdout.writelines(file.readlines())

Should probably be closer to what you want.

Other comments:

s.listen(1)

This statement should probably be moved outside of the while loop. You only need to call listen once.

pipe = os.popen(rc)

os.popen has been deprecated, use the subprocess module instead.

file = s.makefile('r', 0)

You're opening a file, yet you never close the file. You should probably add a file.close() after your sys.stdout.writelines() call.

EDIT: to answer below comment; done here due to length and formatting

As it stands, you read from the socket once, and then immediately close it. Thus, when the client goes to send the next command, it sees that the server closed the socket and indicates an error.

The solution is to change your server code so that it can handle receiving multiple commands. Note that this is solved by introducing another loop.

You need to wrap

rc = conn.recv(2)
pipe = os.popen(rc)
rl = pipe.readlines()
fl = conn.makefile('w', 0)
fl.writelines(rl[:-1])

in another while True: loop so that it repeats until the client disconnects, and then wrap that in a try-except block that catches the IOError that is thrown by conn.recv() when the client disconnects.

the try-except block should look like

try:
    # the described above loop goes here
except IOError:
    conn.close()
# execution continues on...
like image 35
Alex Miller Avatar answered Nov 14 '22 22:11

Alex Miller