简体   繁体   中英

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.

你的代码调用conn.close()然后循环回到conn.recv() ,但conn已经关闭。

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM