Python клиент / сервер вопрос - PullRequest
6 голосов
/ 10 января 2011

Я работаю над небольшим проектом на Python. У меня есть клиент и сервер. Сервер прослушивает соединения, и как только соединение получено, он ожидает ввода от клиента. Идея состоит в том, что клиент может подключиться к серверу и выполнить системные команды, такие как ls и cat. Это код моего сервера:

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()

А это мой код клиента:

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())

Когда я запускаю сервер, я получаю правильный вывод, говоря, что сервер слушает. Но когда я соединяюсь со своим клиентом и набираю команду, сервер выходит с этой ошибкой:

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

На стороне клиента я получаю вывод ls, но сервер облажается.

Ответы [ 2 ]

6 голосов
/ 10 января 2011

Ваш код вызывает conn.close(), а затем возвращается к conn.recv(), но conn уже закрыт.

3 голосов
/ 10 января 2011

Если вы хотите, чтобы ваш клиент повторил то, что он делает, просто добавьте туда цикл;)

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())

Должно быть, вероятно, ближе к тому, что вы хотите.

Другие комментарии:

s.listen(1)

Этот оператор, вероятно, следует переместить за пределы цикла while.Вам нужно всего лишь один раз вызвать listen.

pipe = os.popen(rc)

os.popen устарел, вместо этого используйте модуль подпроцесса .

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

Выоткрыв файл, но вы никогда не закроете файл.Вам, вероятно, следует добавить file.close() после вашего sys.stdout.writelines() вызова.

РЕДАКТИРОВАТЬ: , чтобы ответить ниже комментарий;сделано здесь из-за длины и форматирования

В таком виде вы читаете из сокета один раз, а затем сразу же закрываете его.Таким образом, когда клиент отправляет следующую команду, он видит, что сервер закрыл сокет, и выдает ошибку.

Решение состоит в том, чтобы изменить код сервера, чтобы он мог обрабатывать прием нескольких команд.Обратите внимание, что это решается введением другого цикла.

Вам нужно обернуть

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

в другой цикл while True:, чтобы он повторялся до тех пор, пока клиент не отключится, а затем обернуть егоблок try-Кроме того, что ловит IOError, который выдается conn.recv (), когда клиент отключается.

блок try-Кроме должен выглядеть как

try:
    # the described above loop goes here
except IOError:
    conn.close()
# execution continues on...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...