Python client / server question

孤者浪人 提交于 2020-01-01 09:56:10

问题


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.


回答1:


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




回答2:


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


来源:https://stackoverflow.com/questions/4642345/python-client-server-question

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!